Is it possible to use 8-bit and 16-bit unit numbers when calling Open, or during read/write. If possible, how would one specify the correct declaration?
It is allowed to use integers of any kind to reference an external unit. In Fortran 2008 (but similar is given back to Fortran 90) the rule for an external-file-unit (R902) is merely "scalar-int-expr".
There are things to note, however. First, the units that exist are processor dependent: the processor is entitled to say that a unit number must be representable by default integer. Second, it's the value of the expression that is important in the file connection and data transfer statements: an external unit referenced in an open, close, read, write or inquire statement by 15_int16 is the same as that referenced by 15_int32 (and the same as 15).
This latter point means that it isn't important how the unit numbers are expressed.
open(15_int16, ...)
write(15) ...
write(15_int8) ...
write(15_int32) ...
write(15_int64) ...
are all appropriate (for when those kind numbers are valid).
In Fortran 95 when doing inquire by file/unit the variable given by the number= specifier had to be of default integer. That restriction is no longer in place.
Related
The fortran OPEN statement places a system-dependent error code in the integer given as its optional IOSTAT specifier. For Intel Fortran, I've found the documentation of the error codes on software.intel.com. Starting from this, I could write an function/subroutine that converts iostat-values to human-readable values. Intel also provides a file for_iosdef.for that defines symbolic names for the values.
In principle, I could repeat the same for all supported compilers, but is there some portable way of interpreting the codes, or at least a subset thereof? Plus, for gfortran, there doesn't seem to be an official list, only unofficial lists like on hep.manchester.ac.uk.
If you want to keep it portable, adhere to what the standard says: Fortran 2008 Final Draft page 242 Section 9.11.5 "IOSTAT= specifier":
In short IOSTAT is "processor-dependent".
However there are a few defined values, which are specified in ISO_FORTRAN_ENV:
IOSTAT_EOR (End of record)... negative integer
IOSTAT_END (End of File)... negative integer
IOSTAT_INQUIRE_INTERNAL_UNIT (Inquired an internal file)... positive integer
0 no error nor EOF nor EOR occured
All other errors are positive integers different from IOSTAT_INQUIRE_INTERNAL_UNIT. Their value however is not specified.
A few propertiese can be Inquired with the INQUIRE statement, e.g.: if you are allowed to read or write to the file.
As of Fortran 2003, the IOMSG specifier is available, which allows obtaining human-readable error messages.
Sadly, there is no reliable way to obtain the full error message, as it takes a single CHARACTER(LEN=...) argument, and fills it with as many characters, as the variable can hold, which may include the full path of the file. In my real-world usecase, I had to use at least a CHARACTER(LEN=256) variable.
It also does not allow reacting to specific error conditions at runtime reliably.
I have a read/write operation going on in the Fortran code snippet as follows
OPEN(5,FILE='WKDAT.dat', STATUS='OLD')
OPEN(6,FILE='WKLST.dat', STATUS='UNKNOWN')
I know that by default the unit number 5 is used for input from the keyboard and unit number 6 is used to display on the screen. Also I can use *.
But in the above-mentioned Fortran code unit number is 5 and a file name "WKDAT.dat" is given. So this means that the data is being read from "WKDAT.dat" file. Also there is code unit number 6 and a file name "WKLST.dat" is given. So this means that the data is being written to "WKLST.dat" file.
Is my understanding correct?
As per my basic knowledge:
Unit number 5 is only used to take input from keyboard & unit number 6 is only used to print to console so no files should be involved. But in the code snippet it has both unit number 5, 6 as well as file name.
So both are contradicting :(
In this link http://www.oc.nps.edu/~bird/oc3030_online/fortran/io/io.html they have mentioned the following "When I/O is to a file you must ASSOCIATE a UNIT number (which you choose) with the FILENAME. Use any unit number other than 5 and 6. On some computers, some unit numbers are reserved for use by the computer operating system."
Fortran has no magic unit numbers. The Fortran standard says nothing about 5, 6 or any other valid unit number being used for a special purpose. As such you are free to use the open statement to associate any valid unit number with a file. However traditionally for reasons that pre-date me 5 and 6 have been pre-associated with the keyboard and screen, as you say. Now still you can change the association by use of the open statement and that is fine save for the confusion it can cause, so most people I know recommend avoiding this and using unit numbers of 10 and upwards. Also because 5 and 6 are not guaranteed to be associated with the default input and output devices I would recommend against their use, preferring * or, in more modern code, the named constants input_unit, output_unit and error_unit from the iso_fortran_env intrinsic module.
So in summary you've got the right idea, and I'm not surprised you're confused.
Nothing in the standard says units 5 and 6 have any special meaning although in practice standard input and standard output are often pre-connected to 5 and 6.
Module iso_fortran_env from Fortran 2008 contains constants
INPUT_UNIT
OUTPUT_UNIT
ERROR_UNIT
with the unit numbers where standard input, standard output and standard error are connected. These are allowed to be different than 5 and 6.
Opening a file in unit that is in use causes the unit to be associated with the new file.
For example the Cray Fortran manual says:
Unit numbers 100, 101, and 102 are permanently associated with the
standard input, standard output, and standard error files,
respectively.
That means if you open some other file as unit 5 or 6 standard input and standard output still have some other unit where they are pre-connected and they will not be closed.
This is a C specification question.
We all know this is legal C and should work fine on any platform:
/* Stupid way to count the length of a number */
int count_len(int val) {
char buf[256];
return sprintf(buf, "%d", val);
}
But this is almost guaranteed to crash:
/* Stupid way to count the length of a number */
int count_len(int val) {
char buf[256000000];
return sprintf(buf, "%d", val);
}
The difference is that the latter program blows the stack and will probably crash. But, purely semantically, it really isn't any different than the previous program.
According to the C spec, is the latter program actually undefined behavior? If so, what distinguishes it from the former? If not, what in the C spec says it's OK for a conforming implementation to crash?
(If this differs between C89/C99/C11/C++*, this would be interesting too).
Language standards for C(89,99,11) begin with a scope section with this wording (also found in some C++, C#, Fortran and Pascal standards):
This International Standard does not specify
the size or complexity of a program and its data that will exceed the capacity of any specific data-processing system or the capacity of a particular processor;
all minimal requirements of a data-processing system that is capable of supporting a conforming implementation.
The gcc compiler does offer an option to check for stack overflow at runtime
21.1 Stack Overflow Checking
For most operating systems, gcc does not perform stack overflow checking by default. This means that if the main environment task or some other task exceeds the available stack space, then unpredictable behavior will occur. Most native systems offer some level of protection by adding a guard page at the end of each task stack. This mechanism is usually not enough for dealing properly with stack overflow situations because a large local variable could “jump” above the guard page. Furthermore, when the guard page is hit, there may not be any space left on the stack for executing the exception propagation code. Enabling stack checking avoids such situations.
To activate stack checking, compile all units with the gcc option -fstack-check. For example:
gcc -c -fstack-check package1.adb
Units compiled with this option will generate extra instructions to check that any use of the stack (for procedure calls or for declaring local variables in declare blocks) does not exceed the available stack space. If the space is exceeded, then a Storage_Error exception is raised.
There was an attempt during the standardization process for C99 to make a stronger statement within the standard that while size and complexity are beyond the scope of the standard the implementer has a responsibility to document the limits.
The rationale was
The definition of conformance has always been a problem with the C
Standard, being described by one author as "not even rubber teeth, more
like rubber gums". Though there are improvements in C9X compared with C89,
many of the issues still remain.
This paper proposes changes which, while not perfect, hopefully improve the
situation.
The following wording was suggested for inclusion to section 5.2.4.1
translation or execution might fail if the size or complexity of a program or its data exceeds the capacity of the implementation.
The implementation shall document a way to determine if the size or complexity of a correct program exceeds or might exceed the capacity of the implementation.
5.2.4.1. An implementation is always free to state that a given program is
too large or too complex to be translated or executed. However, to stop
this being a way to claim conformance while providing no useful facilities
whatsoever, the implementer must show provide a way to determine whether a
program is likely to exceed the limits. The method need not be perfect, so
long as it errs on the side of caution.
One way to do this would be to have a formula which converted values such
as the number of variables into, say, the amount of memory the compiler
would need. Similarly, if there is a limit on stack space, the formula need
only show how to determine the stack requirements for each function call
(assuming this is the only place the stack is allocated) and need not work
through every possible execution path (which would be impossible in the
face of recursion). The compiler could even have a mode which output a
value for each function in the program.
The proposed wording did not make it into the C99 standard, and therefore this area remained outside the scope of the standard. Section 5.2.4.1 of C99 does list these limits
The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits:
127 nesting levels of blocks
63 nesting levels of conditional inclusion
12 pointer, array, and function declarators (in any combinations) modifying an arithmetic, structure, union, or incomplete type in a declaration
63 nesting levels of parenthesized declarators within a full declarator
63 nesting levels of parenthesized expressions within a full expression
63 significant initial characters in an internal identifier or a macro name (each universal character name or extended source character is considered a single character)
31 significant initial characters in an external identifier (each universal character name specifying a short identifier of 0000FFFF or less is considered 6 characters, each universal character name specifying a short identifier of 00010000 or more is considered 10 characters, and each extended source character is considered the same number of characters as the corresponding universal character name, if any)
4095 external identifiers in one translation unit
511 identifiers with block scope declared in one block
4095 macro identifiers simultaneously defined in one preprocessing translation unit
127 parameters in one function definition
127 arguments in one function call
127 parameters in one macro definition
127 arguments in one macro invocation
4095 characters in a logical source line
4095 characters in a character string literal or wide string literal (after concatenation)
65535 bytes in an object (in a hosted environment only)
15 nesting levels for #included files
1023 case labels for a switch statement (excluding those for any nested switch statements)
1023 members in a single structure or union
1023 enumeration constants in a single enumeration
63 levels of nested structure or union definitions in a single struct-declaration-list
In C++, Annex B indicates that the maximum size of an object is an implementation-specific finite number. That would tend to limit arrays with automatic storage class.
However, I'm not seeing something specifically for space accumulated by all automatic variables on the call stack, which is where a stack overflow ought to be triggered. I'm also not seeing a recursion limit in Annex B, although that would be closely related.
The C standard is silent on all issues relating to stack overflow. This is a bit strange since it's very vocal in just about every other corner of C programming. AFAIK there is no specification that a certain amount of automatic storage must be available, and no way of detecting or recovering from exhaustion of the space available for automatic storage. The abstract machine is assumed to have an unlimited amount of automatic storage.
I believe the behavior is undefined by omission -- if a 250,000,000-byte local object actually exceeds the implementation's capacity.
Quoting the 2011 ISO C standard, section 1 (Scope), paragraph 2:
This International Standard does not specify
[...]
- the size or complexity of a program and its data that will exceed the capacity of any
specific data-processing system or the capacity of a particular processor
So the standard explicitly acknowledges that a program may exceed the capacity of an implementation.
I think we can safely assume that a program that exceeds the capacity of an implementation is not required to behave the same way as one that does not; otherwise there would be no point in mentioning it.
Since nothing in the standard defines the behavior of such a program, the behavior is undefined. This is specified by section 4 (Conformance), paragraph 2:
[...] Undefined behavior is otherwise indicated in this
International Standard by the words "undefined behavior" or by the
omission of any explicit definition of behavior. There is no
difference in emphasis among these three; they all describe "behavior
that is undefined".
Of course an implementation on most modern computers could easily allocate 250 million bytes of memory; that's only a small fraction of the available RAM on the computer I'm typing this on, for example. But many operating systems place a fairly low limit on the amount of stack space that a program can allocate.
(Incidentally, I'm assuming that the code in the question is a fragment of some complete program that actually calls the function. As it stands, the code has no behavior, since there's no call to count_len, nor is there a main function. I might not normally mention that, but you did use the "language-lawyer" tag.)
Anyone who would argue that the behavior is not undefined should explain either (a) why having the program crash does not make the implementation non-conforming, or (b) how a program crash is within the scope of defined behavior (even if it's implementation-defined or unspecified).
I am new to Fortran 2008 and am trying to implement a Sieve of Atkin. In C++ I implemented this using a std::bitset but was unable to find anything in Fortran 2008 that serves this purpose.
Can anyone point me at any example code or explain an implementation strategy for one?
Standard Fortran doesn't have a precise analogue of what I understand std:bitset to be -- though I grant you my understanding may be defective. Generally, and if you want to stick to standard Fortran, you would use integers as sets of bits. If one integer doesn't have enough bits for your purposes, use arrays of integers. This does mean, though, that the responsibility for tracking where, say, the 307-th bit of your bitset is falls on you
Prior to the 2008 standard you have functions such as bit_size, iand, ibset, btest and others (see your compiler documentation or Google for language references, or try the Intel Fortran documentation) for bit manipulation.
If you are unfamiliar with Fortran's boz literals then familiarise yourself with them. You can, for example, set the bits of an integer using a statement such as this
integer :: mybits
...
mybits = b'00000011000000100000000000001111'
With the b edit descriptor you can read and write binary literals too. For example the statements
write(*,*) mybits
write(*,'(b32.32)') mybits
will produce the output
50462735
00000011000000100000000000001111
If you can lay your hands on a modern-enough compiler then you will find that the 2008 standard added new bit-twiddling functions such as bge, bgt, dshiftl, iall and a whole lot more. These are defined for input arguments which are integer arrays or integers, but I don't have any experience of using them to pass on.
This should be enough to get you started.
Fortran has bit intrinsics for manipulating the bits of default integers. Bit arrays are straightforward to build off that...
Determine how many bits you need, divide by number of bits in default integer, allocate an integer array of default kind of the size you computed +1 if the modulo of the division was non-zero, and you're essentially done. The bit intrinsics are well covered in Metcalf and Reid.
What you may want could look like:
program test
logical,allocatable:: flips(:)
...
allocate(flips(ntris),status=err)
call tris(ntris,...,flips)
...
end
subroutine tris(nnewtris, ...,flips)
logical flips(nnewtris)
...
if(flips(i)) then
...
end if
return
end
I've ported some Fortran code from Fortran PowerStation(4.0) to the Fortran 11(2003) compiler. In order to maintain double and real values between the old and new compiler, I changed properties>fortran>data>"Default Read Kind" from 4 to 8. Now the problem is that the global variables are not maintaining data from one file to other.
Suppose I create a real*8 variable called abc in one file as a global variable (COMMON/test/abc). It is modified in one file and used in another file. When inspecting the value of the abc variable in the second file, it is found not to contain the modified data. This happens only when I change "Default Real Kind" to 8.
Are there any other options I need to modify from the properties window?
Please give a solution. Thanks in advance.
I'm a bit unclear about what compiler you are using, what modifications you have made and so forth, so my answer is a bit hesitant.
I'm not sure that changing the default real kind from 4 to 8 does maintain values as you think it does. You seem to think that real(kind=4) on your old compiler means the same as real(kind=8) on your new compiler. This may be true, but it seems a bit unlikely to me.
However, don't fall into the trap of thinking that real(kind=4) must mean a 4-byte IEEE compliant floating-point number, or that real(kind=8) must mean an 8-byte IEEE fp number. This is true for most compilers, certainly for all the compilers I've used recently, but it's not required by the Fortran standard. Your old compiler may have meant something different from what your new compiler means.
Finally, I usually experience problems with common blocks when I change real number sizes in Fortran programs. The best solution is to replace common blocks with module variables. If you can't do that, check the common declarations very carefully, bearing in mind that common is an instruction to the compiler about how to lay variables out in memory. If you change the size of a variable in one declaration of the common block but not in another you will have problems.
Regards
Mark