Thanks! Just curious, if printing can cause crashes or segfaults errors when -O2/O3 is enabled, then why a debugger will not cause crashes or segfaults errors?
Sorry, maybe I wasnât clear. I didnât mean the print causing the crash. What I meant is: your application might crash or segfault for which ever reason, then you want to know why, so you switch the debug mode, but now everything works⌠so you might need to go back to release mode but putting prints to find where the problems is by dichotomy. This is what I meant by âdebug by printing as your last resortâ. The reasons for a crash or segfault in release not happening in debug mode are multiple and I prefer not to bloat this thread with that topic.
Thank you. Indeed I believe that compilers must lead the change and implement new features and optimizations and only then things should be standardized. Not the other way around, which indeed leads to the infinite loop of not getting what we want as users. ![]()
I think this was the way things worked up until Fortran 90 (and later Fortran 2003). My understanding (and folks who know the history of Fortran 90 better than me can correct me if Iâm wrong) is that there were major battles among the Committee members at that time (particularly the commercial vendors) about what should be added to the language. After Fortran 90, I donât remember many if any vendors implementing new features that werenât first proposed by someone on the committee. I guess to avoid the implementation costs associated with major language revisions there is a reluctance on the part of the commercial vendors to lead rather than follow.
The book âNumerical Recipes in Fortran 90â has a very interesting discussion related to the âfightâ in the committee.
There were several features in f77 that had not previously been implemented as compiler extensions, at least not in any of the earlier compilers I used. Three that come to mind are the character data type (with LEN(), substring notation, and the concatenation operator), the PARAMETER statement, and the SAVE statement. [DEC implemented a form of PARAMETER from an early f77 draft, but the final f77 semantics and syntax were different, and DEC decided to support both versions, confusing programmers for over a decade.] All three of those features live on today in modern fortran, suggesting that they were well designed by the committee and popular among programmers.
On the other hand, there were many popular extensions that did not get standardized in f77, including namelist i/o, asynchronous i/o, bit intrinsic operators, query of command line arguments, date and time query, and double precision complex.
In f90, I think ALLOCATABLE arrays were first proposed (in the fortran 8x drafts) before the feature was implemented as an extension in any f77 compiler. The competing syntax extensions were the quirky âcray pointerâ and the somewhat embarrassing to say aloud FALLOC() intrinsic. I can see why the committee invented something new here instead of standardizing those earlier extensions.
edit: âdirect accessâ changed to ânamelistâ in the above comment.
Direct access I/O was in Fortran 77 - though in different and better form than the IBM DEFINE FILE and random access read/write syntax. The feature was slightly incomplete - until INQUIRE(IOLENGTH=...) became standardized in F90.
Shortly after the Fortran 77 Standard was published, the DOD published their MIL-STD-1753 - which defined bit intrinsics and several other features (e.g., INCLUDE, DO WHILE, END DO). They were inconsistently implemented, but eventually made their way into Fortran 90.
Time and date intrinsics would have been nice in Fortran 77. I guess not too many people were thinking about Y2K at the time. Though interestingly, one of the first bugs I fixed in my new job in Jan 1980 was a âY10â bug. The program broke when the year changed from 1979 to 1980, because it was doing some input validation checks and figured dates not in the '70s would be out of range. I fixed it so it also accepted dates in the '80s. (By 1990 I was long gone, so have no idea if it broke again.
)
Yes, of course you are right. I was thinking NAMELIST I/O, and I wrote DIRECT ACCESS I/O. I will edit my earlier post to correct this error. You are also correct about the RECL/IOLENGTH issue.
The original programmer was obviously not thinking long term.
I asked him (my 2nd level manager at the time) about it. He was surprised they were still using the program! I suspect it was gone by 1990, but one never knows.
Brian Meek wrote a very good paper that people may like. Here is a link https://www.fortranplus.co.uk/app/download/23714308/brian_meeks_fortran_saga.pdf
What are peopleâs immediate impressions/understanding for elemental functions on (simple) derived types. Something like a complex 3x3 matrix.
I used an in-house production code where it is extremely common to have rank(5) arrays of such a derived type. Often there would be a function to take two of these and do a loop element wise over 4 of these ranks. This could be an elemental function - but should it?
A simple example is something like this (though sum is not a useful operation)
program dtC3x3
implicit none(external)
type SU3ColourMatrix
complex, dimension(3,3) :: cl
end type SU3ColourMatrix
type(SU3ColourMatrix), dimension(2) :: U
complex, dimension(2) :: summed
U(1)%cl = (1.0, 2.0)
U(2)%cl = (2.0, 1.0)
summed = mySum(U)
contains
pure elemental function mySum(U) result(res)
type(SU3ColourMatrix), intent(in) :: U
complex :: res
res = sum(U%cl)
end function mySum
end program dtC3x3
It would be nice if a compiler had an option to warn about procedures that could be declared pure, elemental, or simple but are not, so that adding these attributes could be automated.
Regarding whether to write elemental procedures, LLMs continue to improve at generating code from prompts in English. If you give them Fortran code that invokes elemental procedures, it should be possible for them to generate alternative versions with do and do concurrent in the caller, since this is a more well-defined task than generating Fortran code from natural language.
@CRquantum loops are essential when the ordering of iterations matter. For example, in a solver that computes successive time steps, one must respect causality: old steps must come before new steps. Restricting loops to such situations communicates to the reader and the compiler where ordering does and doesnât matter.
Array statements arenât the only alternative. I havenât attempted to compile a comprehensive list, but a few other alternatives are do concurrent, where, elemental, including every elemental intrinsic function, which I suspect is a long list. Moreover, intrinsic functions such as pack, findloc, count operate on whole arrays or array sections in ways that would require loops and additional logic if these functions didnât exist.
I agree that the processing order of the array elements is unspecified with do concurrent and where, but I think not so with elemental.
I was just working with some elemental subprograms, and I learned (or relearned) that the elements of the array arguments are processed in array element order. This is specified, for example, in section 15.9.3 of the f2023 standard.
An odd thing however, is that this order is specified only for intent(out) and intent(inout) arguments. In one of my cases, there was a single intent(in) argument. My compiler processed the result in array element order, as I expected, but I am unsure if that specific case is actually covered by the standard. In my code, I did not care what was the order, but I could imagine situations where order might actually matter and I wondered why the intent(in) case was not included in that paragraph of the standard. I suspect that it is an oversight, possibly associated with the recent addition of the impure subprogram attribute. I could find no language that disallowed or otherwise restricted intent(in) arguments, but I could also not locate any other text in the standard that covered this situation. Did I overlook something regarding this situation in the standard, or did the standard overlook this case?
@RonShepard thanks for pointing that out! I wasnât aware of that either. Section 15.9.3 in the Fortran 2023 standard applies only to subroutines. It therefore doesnât affect most elemental procedures that I write because almost all are functions. I just surveyed the src subdirectory of two of my projects, Julienne and Fiats, and found that subroutines constitute only 5 out of 166 elemental procedures in the two projects. For reasons related to adopting a functional programming style, I tend to write mostly functions.
I suspect the reason for specifying order for intent(out) and intent(inout) is that the ordering is less likely to matter if the arguments are not modified. Specifically, if it is desired to parallelize across invocations, the likelihood of race conditions is lower if a procedure doesnât modify its arguments. This also hints at why 15.9.3 does not apply to functions. An elemental function is pure unless declared impure. A pure functionâs dummy arguments must have the intent(in).
However, I think youâve found an issue with the standard. 15.9.3 was probably written before impure was added in Fortran 2008. I suspect that one could write an impure elemental function that would be allowed to have dummy arguments with the intent(out) or intent(inout) attribute. For consistency, the standard should probably specify the order of evaluation for an impure elemental function to match the order for an elemental subroutine.