I read a binary file and want to specify the position in read statement:
READ(IOUNIT,IOSTAT=IOSTAT, POS=POSITION)
What I'm wondering is the type of POSITION. All examples I was was able to find had POSITION declared as a 4 byte integer. Is it possible to have it an 8 byte integer?
Under the Fortran standard (Fortran 2018, R1213, 12.6.2.1; similar back to Fortran 2003) , the POS= specifier to the read statement must be a scalar integer expression. There is no specific restriction on the kind of that integer.
If your Fortran processor supports 8-byte integers then such an integer can be used in the specifier where that specifier is supported (in particular, under stream access, hence Fortran 2003 being mentioned earlier).
Related
I read an unformatted, binary checkpoint file with fortran and need to check the values for their validity. The whole point of the checkpointing is that there was some crash and the checkpoint file itself could be corrupted (e.g. if the crash happened during writing the file).
So my question now: Is there is a standard procedure to check if logical values read from a file were stored correctly as logical values.
A short test with writing any number instead of the logical and reading it gave me a .false. value. I assume every number that is read will be converted following the C-like rule: nr==0 ->.false. nr!=0 -> .true.. This is however not helping me to discern if the logical was written correctly.
What I could imagine is reading the value as integer (or some kind of binary value?) first and checking if they are 0 or 1, pointing to a proper writing of the logical.
Example:
write_test.f90:
program write_test
logical,parameter :: bool=.true.
real*8,parameter :: r=5e20
open(unit=10,form='unformatted')
write(10)bool,r
close(10)
end program
read_test.f90:
program read_test
logical :: bool1
logical :: bool2
open(unit=10,form='unformatted')
read(10)bool1,bool2
write(*,*)bool1,bool2
end program
Output of read_test.f90:
T F
bool2looks as if it was a nice logical with the value .false., but it was stored as a real, which I would like to avoid as well as all other data-types that might get thrown there.
Apparently it is also not using .true. for a values other than 0. My guess is that the leading bit of the real that is stored there is 0 and it is only reading this single bit.
This is perhaps an extended comment rather than an answer:
You are wrong when you assume every number that is read will be converted following the C-like rule: nr==0 ->.false. nr!=0 -> .true. or at least, your assumption is not guaranteed to be true by the rules of the Fortran standard. This is silent on the issue of the bit patterns used to represent True and False, in particular it does not mandate that they should be the same as the bit patterns used to represent 0 and 1 (or 1 and 0 - I can never get the hang of those funny languages that think those are boolean values).
Just about all that the Fortran standard does guarantee is that default-sized reals, integers and logicals occupy the same number of bits in memory and (unless you fiddle about with them) when written unformatted to file. This means, inter alia, that any 32-bits (or 64 if that is your default storage unit size) can be interpreted as a real, an integer or a logical.
Some of the bit patterns may not be interpreted successfully as any or all of those types, but again that is an implementation issue below the level at which the Fortran standard operates.
It's impossible to know, from the bits alone, what type of value a group of 32 bits represents, there has to be a description somewhere of how to interpret binary files. This is what makes them rather unportable.
If these issues matter to you you really have to investigate them for yourself, in particular, what bit patterns does your compiler (version) use to represent the logical values. You can reasonably expect (though this stops short of a guarantee) that integers are represented in two's complement form and reals in IEEE form.
This question already has answers here:
Transfer integer to string
(1 answer)
End of Record error when saving a variable
(2 answers)
Closed 4 years ago.
The program below errors out at runtime
program exmple
implicit none
character(len=10)::FT
write(FT,*)int(0.75*100)
end
This gives the error
output statement overflows record, unit -5, file Internal List-Directed Write
In order to remove the error I need len=12 or greater. My question is simply why? What determines the length necessary for an int to string?
In case it is useful I am compiling with ifort v 14.0.2
According to section 10.10.4 (List-directed output), Note 10.33 of the Fortran 2008 standard, when the format is not specified
The length of the output records is not specified and is processor dependent.
This concerns both external and internal files.
I suggest using '(i0)' as the format when writing an integer to a string in such conditions: according to the standard, section 10.7.2.1, paragraph 1 (5),
On output, with I, B, O, Z, F, and G editing, the specified value of the field width w may be zero. In such cases, the processor selects the smallest positive actual field width that does not result in a field filled with asterisks.
What determines the length necessary for an int to string?
If you are not specifying a format, it is compiler-dependent. To know for your specific compiler, just do a print and check the output (in my ifort 18 it is 12 too).
Anyway, you shouldn't count in this behavior because it wont be portable at all. If posible, use a formated output.
EDIT: Just a hint on how the compilers choose the length of a unformatted integer. The maximum representable integral number by a default integer (usually 4 bytes) is 2^31 - 1 = 2147483647 and this is a 10 digits number. Add one more character for a posible minus singal, and one space for separating it from the previous record, you get 12.
OpenGL specification says that all types has fixed bitdepths. Also as I know c++ specification doesn't regulate bitdepth. There is only thing that we know: c++ types like int32_t, int16_t,... contains need number of bytes, but not bits. How we can safely use these types? And how can we be sure that say OpenGL type "unsigned integer" will match with uint32_t at binary representation level?
There is only thing that we know: c++ types like int32_t, int16_t,... contains need number of bytes, but not bits.
That's not true at all. The C standard, which the C++ standard imports, states:
The typedef name intN_t designates a signed integer type with width N, no padding bits, ...
N being the number of bits, not the number of bytes.
The OpenGL standard similarly defines its types with an exact number of bits, not bytes. Neither one allows padding.
Therefore, GLuint must be identically sized and formatted relative to uint32_t. They need not be the exact same type, but since they store the same range of values and have the same size, conversion between them ought to be lossless.
So it's not clear what you're concerned about.
I'm trying to learn Fortran and I'm seeing a lot of different definitions being passed around and I'm wondering if they're trying to accomplish the same thing. What is the difference between the following?
integer*4
integer(4)
integer(kind=4)
In Fortran >=90, the best approach is use intrinsic functions to specify the precision you need -- this guarantees both portability and that you get the precision that you need. For example, to obtain integers i and my_int that will support at least 8 decimal digits, you could use:
integer, parameter :: RegInt_K = selected_int_kind (8)
integer (kind=RegInt_K) :: i, my_int
Having defined RegInt_K (or whatever name you select) as a parameter, you can use it throughout your code as a symbol. This also makes it easy to change the precision.
Requesting 8 or 9 decimal digits will typically obtain a 4-byte integer.
integer*4 is an common extension going back to old FORTRAN to specify a 4-byte integer. Although, this syntax isn't and was never standard Fortran.
integer (4) or integer (RegInt_K) are short for integer (kind=4) or integer (kind=RegInt_K). integer (4) is not the same as integer*4 and is non-portable -- the language standard does not specify the numeric values of kinds. Most compilers use the kind=4 for 4-byte integers -- for these compilers integer*4 and integer(4) will provide the same integer type -- but there are exceptions, so integer(4) is non-portable and best avoided.
The approach for reals is similar.
UPDATE: if you don't want to specify numeric types by the required precision, but instead by the storage that they will use, Fortran 2008 provides a method. reals and integers can be specified by the number of bits of storage after useing the ISO_FORTRAN_ENV module, for example, for a 4-byte (32-bit) integer:
use ISO_FORTRAN_ENV
integer (int32) :: MyInt
The gfortran manual has documentation under "intrinsic modules".
Just one more explicit explanation what the kind is. The compiler has a table of different numerical types. All integer types are different kinds of the basic type -- integer. Let's say the compiler has 1 byte, 2 byte, 4 byte, 8 byte and 16 byte integer (or real) kinds. In the table the compiler has an index to each of this kind -- this index is the kind number.
Many compilers choose this numbering:
kind number number of bytes
1 1
2 2
4 4
8 8
16 16
But they can choose any other numbering. One of the obvious possibilities is
kind number number of bytes
1 1
2 2
3 4
4 8
5 16
There are indeed compilers (at least g77 and NAG) which choose this approach. There are also options to change this. Therefore kind numbers are not portable integer(kind=4) or integer(4) means a 4 byte integer or a 8-bytes integer depending on the compiler.
integer*4 is portable in the sense it always means 4 bytes. But on the other hand it is not portable because it has never been part of any standard. Programs using this notation are not valid Fortran 77, 90 or any other Fortran.
To see the right options how to set the kind numbers see M.S.B.'s answer.
The same concept holds for real data types. See Fortran 90 kind parameter (the mataap's answer).
I will make reference to this enlightening article, wrote recently by #SteveLionel, and try cover some details that are not present in the other answers so far:
The syntax shown in integer*n or real*n was a common extension provided by compilers long time ago, when different computer architectures started to have different designs for in-memory format of integer and real values, where n was the size in bytes of the value stored. However, that said nothing about range or precision of those values: different implementations of a 16bit integer, for example, could provide different ranges and limit values.
Register sizes could be 8, 12, 16, 30, 32, 36, 48, 60 or 64 bits, some CDC machines had ones-complement integers (allowing minus zero for an integer!), the PDP-11 line had several different floating point formats depending on the series, the IBM 360/370 had "hex normalization" for its floating point, etc [...] So popular were these extensions that many programmers thought (and even today many think) that this syntax is standard Fortran; it isn't!
When Fortran 90 came out, kind parameters were added to the language, along with intrinsic inquiry functions (specially kind, selected_int_kind and selected_real_kind, but also others, like precision, digits, epsilon...) to aid the programmer to specify minimun requirements for precision and range of numeric types (still, no official mention to storage model or bytes). The syntax is integer(kind=n) or even integer(n), where n is a constant value corresponding to a kind of integer supported by the compiler. For literal constants, the syntax is 12_n or 3.4e-2_n.
The advantage of this solution was that Fortran didn't (and still don't) make any assumptions about the implementation details of data-types other than the results of the inquiry functions used to choose the type, so the code is parameterized by the problem being solved, not by the language or the hardware. The gotcha is, as said in other answers, each compiler can choose their kind numbers, thus assuming magic number like integer(4) is not portable.
Also with Fortran 90 came the concept of default kinds, that is what you get when you don't specify a kind.
The default kinds were implementation dependent, though up through Fortran 2008 a compiler was required to support only one integer kind and two real kinds. (That's still true in Fortran 2018, but there's an added requirement that at least one integer kind support 18 decimal digits.) If you write a constant literal without a kind specifier, you got the default kind.
With Fortran 2003 and the inclusion of the intrinsic module ieee_arithmetic, you can inquire and select a real type with IEEE floating point capabilities, if avaliable.
There are architectures where both IEEE and non-IEEE floating types are available, such as the HP (formerly Compaq formerly DEC) Alpha. In this case you can use IEEE_SELECTED_REAL_KIND from intrinsic module IEEE_ARITHMETIC to get an IEEE floating kind. And what if there is no supported kind that meets the requirements? In that case the intrinsics return a negative number which will (usually, depending on context) trigger a compile-time error.
Finally, Fortran 2003 brought the iso_fortran_env intrinsic module, that had functions to inquire the storage size of the types implemented by a compiler, with intrinsics like numeric_storage_size and bit_size. Another addition of Fortran 2003 revision was the iso_c_binding intrinsic module, that provided kind parameter values to guarantee compatibility with C types, in storage, precision and range.
Intrinsic module ISO_C_BINDING declares constants for Fortran types that are interoperable with C types, for example C_FLOAT and C_INT. Use these if you're declaring variables and interfaces interoperable with C.
As a final note, I will mention the recent Fortran 2008 Standard, that extended intrinsic module iso_fortran_env to include named constants int8, int16, int32m int64, real32, real64 and real128, whose values correspond to the kinds of integer and real kinds that occupy the stated number of bits. The gotcha is that those constants only assure storage size, not precision or range. Only use them when this is exactly what you want.
In my view, this is little better than the old *n extension in that it tells you that a type fits in that many bits, but nothing else about it. As an example, there's one compiler where REAL128 is stored in 128 bits but is really the 80-bit "extended precision" real used in the old x86 floating point stack registers. If you use these you might think you're using a portable feature, but really you're not and may get bitten when the kind you get doesn't have the capabilities you need.
The manual of a program written in Fortran 90 says, "All real variables and parameters are specified in 64-bit precision (i.e. real*8)."
According to Wikipedia, single precision corresponds to 32-bit precision, whereas double precision corresponds to 64-bit precision, so apparently the program uses double precision.
But what does real*8 mean?
I thought that the 8 meant that 8 digits follow the decimal point. However, Wikipedia seems to say that single precision typically provides 6-9 digits whereas double precision typically provides 15-17 digits. Does this mean that the statement "64-bit precision" is inconsistent with real*8?
The 8 refers to the number of bytes that the data type uses.
So a 32-bit integer is integer*4 along the same lines.
A quick search found this guide to Fortran data types, which includes:
The "real*4" statement specifies the variable names to be single precision 4-byte real numbers which has 7 digits of accuracy and a magnitude range of 10 from -38 to +38. The "real" statement is the same as "real*4" statement in nearly all 32-bit computers.
and
The "real*8" statement specifies the variable names to be double precision 8-byte real numbers which has 15 digits of accuracy and a magnitude range of 10 from -308 to +308. The "double precision" statement is the same as "real*8" statement in nearly all 32-bit computers.
There are now at least 4 ways to specify precision in Fortran.
As already answered, real*8 specifies the number of bytes. It is somewhat obsolete but should be safe.
The new way is with "kinds". One should use the intrinsic functions to obtain the kind that has the precision that you need. Specifying the kind by specific numeric value is risky because different compilers use different values.
Yet another way is to use the named types of the ISO_C_Binding. This question discusses the kind system for integers -- it is very similar for reals.
The star notation (as TYPE*n is called) is a non-standard Fortran construct if used with TYPE other than CHARACTER.
If applied to character type, it creates an array of n characters (or a string of n characters).
If applied to another type, it specifies the storage size in bytes. This should be avoided at any cost in Fortran 90+, where the concept of type KIND is introduced. Specifying storage size creates non-portable applications.