Old content (this is from 1992) should have a year in the title. This is a summary of Fortran 77. The latest standard is Fortran 2018, and Fortran 202x is being worked on. Some features of Fortran 2018 have been implemented in compilers.
I find it remarkable that modern Fortran implements many advanced features while remaining backward compatible with Fortran 77, which, visually, looks like a different language.
Fortran 90 introduced 'free form', a more modern syntax compared to ye olde FORTRAN. Typically free form source code is denoted by a '.f90' extension whereas '.f' is for the old style fixed form.
It is weird that Fortran was modernized 30 years ago, but the old prejudicies live on. Maybe programming languages teachers in CS departments are now telling their students the same jokes "look how primitive FORTRAN is" that their own teachers told them a generation earlier. So the primitive FORTRAN 77 lives on in Computer Science lore, while Fortran 90/95/03/08/13 is what people in the actual number crunching community use.
Let's wait until 2050s and see, whatever Fortran 2050 will be like, if CS people will still joke about Fortran as if it was FORTRAN 77.
People will joke about the primitiveness of Fortran as long as they are required to preface every module and program with `implicit none`. Also, every time they pick up lapack and need to specify the "leading dimension of A" they will recall how Fortran had it's roots in a language without dynamic memory allocation and how they're still living with that legacy. Fortran's legacy leaks all over the place: you rapidly get a feel that it is something which is old and creaky, even if it is actually old and rock solid. The ergonomics are very much not modern, though, but as with all discussions of ergonomics, that is going to depend on how you like to hold your tool.
Not that other languages which have widespread support also have similar historical mistake leakage. Null vs Optional in Java comes to mind. The python 2 -> 3 debacle was a similar sort of "historical mistake correction" but the breakage of backwards compatibility lead to quite some polarization. Actually, in python 2 -> 3, the python core developers tried to fix a historical defect that fortran still has: print as a keyword vs a function.
<as long as they are required to preface every module and program with `implicit none`>
A small price to pay for being able to run code from 60 years ago. And no, there is no such requirement as such.
<need to specify the "leading dimension of A">
A very clever way of applying your algo to a submatrix from the days of sequence association and no array expressions. Nothing to do with dynamic memory allocation and you know the compiler will have no excuse to copy data.
Why is it a defect that I/O needs keyword? Fortran has doubled-down on that "defect" by making coarray references through syntax [] and not an MPI-like procedure call. I don't think it's a defect at all, it's a strength.
I really don't understand why you're arguing with my explanation. I'm not attacking fortran, I'm explaining why it will feel old to people: because it has things in it that people moved on from. Heck, I'd even agree that it is a sort of bad attitude to automatically discount something because of such legacy. But there are clear historical artifacts in the language (like most languages today).
> A very clever way of applying your algo to a submatrix from the days of sequence association and no array expressions.
This isn't why you specify the leading dimension, it is just a useful feature of the leftover artifact of the lack of dynamic allocation. If the algorithms were written today, the array slicing notation would simply be used to achieve that.
Back in Fortran 66 days, you would compile a large 2d array to solve the biggest problem you wanted to solve because you couldn't dynamically allocate. The alternative would be to change the source code and compile, but that was untenable. Then you would set your array elements with ordinary matrix notation but you would need to specify the stride to the solver to work with that: thus yes, it was solving a block, but it is only capable of solving the upper block. So clearly not intended for general submatrix solving: it is meant for using the upper block of a matrix in lieu of dynamically allocating the matrix to the correct size. Alternatively they could have required people to work with 1d arrays and manually handle the matrix indexing, but that would have been unfriendly.
We have moved on, from a compiler that could fit in 4kbytes of main memory to one that is a 2Gigabyte download.
It was “array slicing” (array expressions) that was missing in F77. That’s what sequence association was meant to help with. You pass a scalar that is an element of an array and the corresponding dummy is an array. The dummy gets associated with an array that starts at that element and then continues with all the other elements of the actual argument array in array element order. You then use the LDA argument to give a 2d view of the same array in the dummy so you can step to the next column (or every other column if you want, just double the LDA) no matter where you started from.
Programs back then had no need for dynamic memory, they were the only thing running on the machine, no kernel, no other processes or users, why not just grab the entire memory? They booted in a blink of an eye, too. Now, not even our supercomputers run like that. You never know who else is using the resources of the machine.
Yes, I am well aware of what it is doing and we won't really make any progress until you can believe that I know the language. We are disagreeing about the intent and rationale of its addition.
Everytime someone tries to interact with DGETRF for the first time, they look up the API (at http://www.math.utah.edu/software/lapack/lapack-d/dgetrf.htm... maybe) and read, "The leading dimension of the array A. LDA >= max(1,M)." Which tells them nothing, so they keep digging through the documentation. Maybe they check the user's guide, https://www.netlib.org/lapack/lug/node116.html and they read "However an assumed-size array declaration has been used in the software, in order to overcome some limitations in the Fortran 77 standard." but sadly their journey is still not over because none of these source have characterized it as you are (as an array stride due to memory layout). Nor named it appropriately. They still have to keep digging to understand it as a stride.
Its name reflects the fact that it was common to oversize the allocation of the memory for the matrix and then LDA > M of course, because in fact LDA = M_MAX. The leading dimension of the matrix in memory (the stride if you were dealing with a 1-d array). If they are lucky (as I was), they will have access to some of the older software that was doing this and they can see what the purpose of the argument and the rationale of the name is. That this also enables one to focus on a sub-block of A and give a stride value. But certainly that isn't the "leading dimension of A". It is the leading dimension of A precisely when A is a bigger matrix and you are focused only on the upper block because of static allocation of A.
If you know the language, you will be aware that the word "memory" is not used in the Standard, except in non-normative sections (i.e. Notes), the keyword SYNC MEMORY (whose specification is not about memory but "segments" for the purpose of managing coarray programs) and the section dealing with interoperability with C (because C is a systems programming language where memory addresses are used). "Memory layout" is not specified in Fortran. Array element order and sequence association and storage association are the terms. I prefer to argue about a language using its terms of reference.
To summarise: F77 has no array expressions so the only way to pass a subobject of an array is through sequence association, as described.
If it had dynamic allocation and no array expressions, sequence association would still be needed. In fact, most F77 compilers supported dynamic allocation as a non-standard extension and STILL used sequence association to pass subobjects of arrays.
Whether you pass a whole array or use sequence association, the meaning of LDA is clear: it determines how sequence association will work between rank-2 dummy and actual array. And, yes, you can use different LDAs (as long as you don't step over the bounds) to effectively walk the diagonal or skip columns.
As I said, it is a historical argument to argue why something was designed in a particular way. You do not seem at all interested in attempting a historical argument. You aren't going to convince me without offering something in the way of common uses of block matrices in numerical linear algebra in the early 70s or without technical notes describing the intent of the parameter to be used for general block submatrix purposes.
Yes, what you are saying is correct about the technical capabilities of the parameter; I have agreed with you 3 times already, but it is irrelevant. You keep ignoring the actual point: an answer of what you can use the parameter for is not the same as an answer to why that parameter is there. You can be quite right about what the parameter allows you to do and quite wrong about why it was added in the first place.
The origin of LDA as an argument traces all the way back to LINPACK. Just read chapter 1 of the LINPACK user's guide, https://doi.org/10.1137/1.9781611971811.ch1 and see them using the parameter as I describe. It is used precisely to over allocate an array in a program so that it can be dynamically sized at runtime. The allocate an array A of size 50 x 50, specify LDA to be 50, then assign N to some value and use 2d array notation to set a block of the array A to a matrix. My assertion is that is precisely the use case they designed that parameter to be used for. That usage is why algorithms with LDA are first class and there are no variants (and they offer many variants) without it: because they knew that people would compile programs with overallocated arrays and require it.
LINPACK predates even fortran 77, tracing back into subroutines developed by Wilkinson this sort of use arises from fortran 66. I'm having a hard time finding technical notes describing those routines though. I'm curious if LDA shows up in the ALGOL 60 versions. In any case all this history was relayed to me by my supervisor who worked worked much closer to this history than me so I trust that quite implicitly.
For you, maybe it was enough to see that the parameter was a stride and stop digging. For me, I saw that, saw it always being set equal to N (and M = N) in all actual uses in the modern code I was working with and I was curious why it wasn't abstracted away because even at Fortran 77 is was easy to hide it behind a zero cost abstraction. So I went down the historical rabbit hole. Maybe I should have just pointed out that the names of the subroutines are limited to 6 characters because of history and you would have agreed that use of LAPACK is a trigger for most people to realize that fortran is filled with historical artifacts.
describes use of Fortran dummy arrays before Fortran IV. No LDA/B/C in the example provided. But I find it hard to believe that once a compiler existed that would compile that example, people took more than a week to realize that by adding LDA/B/C you can write a general DGEMM that can multiply submatrices.
We need to remember that first there was a compiler implementation and the language was secondary to that. Language extensions that the compiler could do "easily" get implemented quickly. Sequence association was one of those things and I still maintain that it would be needed (in the absence of array expressions) even if there was dynamic allocation in Fortran I.
Consider a subroutine that is expected to take the 1st column and the last column of an array, sum them, and put the result in the 1st column. You want to write
Can you reuse sub to only sum the bottom half of the columns? Not without allocating a new array and copying before passing the copy to sub. With sequence association, LDA and adjustable or assumed-size arrays and extra integer arguments, you can and it will work for any rank.
The alternative coding that I have seen (and abhor), is putting an LDA in a COMMON and then all your subroutines pick up an LDA from there. Such codes are usually riddled with errors.
> it was solving a block, but it is only capable of solving the upper block. So clearly not intended for general submatrix solving: it is meant for using the upper block of a matrix in lieu of dynamically allocating the matrix to the correct size.
Nope, you can solve any submatrix by passing the address of some other element than the upper left corner as the address of the array.
Except that LOC doesn't take an offset and pointer arithmetic in fortran isn't guranteed to be safe. No practitioner that I ever worked with ever used them besides. I mean you could have simply argued that malloc existed.
Anyways, from the original guide of fortran (maybe I am mischaracterizing their rationale, but from the horse's mouth):
> However an assumed-size array declaration has been used in the software, in order to overcome some limitations in the Fortran 77 standard. [LAPACK Users' Guide Third Edition]
It doesn't matter what the real reason is. The interface to matrix solving algorithms is archaic feeling:
DGTTRF( N, DL, D, DU, DU2, IPIV, INFO )
DGTTRS( TRANS, N, NRHS, DL, D, DU, DU2, IPIV, B, LDB, INFO )
Yes, I understand the purpose of every argument, I even understand the weird naming convention. Everything about this feels old and a newer language (such as a newer fortran) could just give you
x, _ = A.solve(b)
Or something similar and still manage to capture the dynamic sizing, the efficient tridiagaonal storage, sub-block structure if needed, and error information via info; you can trivially make a signature that does it in place if you don't want a silently copying version.
There's that LDB, and it certainly has nothing to do with a sub-block of the matrix since it has to do with the storage of the right hand side and enabling a single call to provide multiple solutions while assuming a particular array layout.
Anyways, nobody is really engaging with the real point: that it is obvious with use that Fortran is an old language because there are all kinds of these historical artifacts laying around. As I said, everyone knows it, everyone who interacts with it will feel it. But by now fortran isn't alone in this camp. Moreoever, so what? You should be able to admit to yourself that Fortran is an old language (that is simply a fact), that it gives the impression to most people of being an old language (that is again, simply a fact and why shouldn't it?), yet it has many modern features and people can be quite productive in it for some problem domains. Adding modern features isn't going to win people over that are prejudiced against Fortran.
"pointer arithmetic" is not Fortran. The Fortran POINTER should not be confused with a C pointer (POINTER has more information). You cannot do arithmetic with a TYPE(C_PTR), either.
LDB allows you to solve the 3rd and 5th RHSs only, when B is dimensioned (1000,100): call with NRHS=2, B=B(1,3) and LDB=2000
You can write a type-bound procedure call
x = A%solve(b)
with today's Fortran. LAPACK calls can be hidden from the casual user. I doubt that a casual user of C++ would enjoy looking at the implementation of its standard library, either.
Yes, 29 year-old code written to a 43-year old standard looks old. How is that a Fortran issue? Would it look any newer if it was written in another 40-year old language? The fact that this code is still the mainstay of scientific computation is evidence of the strength of its design and the design of the programming language.
C++ suffers from the same fate, you see some people talk here about how modern C++ fixes many of the flaws and so on, yet those same CS teachers keep teaching C+ (no typo) as if we were in 1994 or something.
Or C like K&R C book was just published yesterday.
The usual response is to ask what's the share of modern FORTRAN compared to old FORTRAN. If most of the people working with FORTRAN work with the old one and don't modernize it, then the reputation is deserved.
No such thing as modern FORTRAN. It’s been “Fortran” for the last 31 years.
People don’t modernize their codes because the Fortran compilers allow them to, and the Standard is reluctant to delete old features (and compilers would not delete them anyway).
Unfortunately, that means that old bugs can lie undetected. I don’t think any other language/compilers have squared that circle.
And there’s plenty of new projects started in Fortran.
Replace "modern FORTRAN" with "mostly FORTRAN 90" then. The person I replied to was saying that FORTRAN's reputation as a old and antiquated language may not be deserved because there are new standard. My question was: are they actually used? If 99% of the C++ in the wild is C++98 and lower, C++11 and higher existing don't make it a "modern" language. Most people will work with the old version, and thus it would deserve a reputation as old and antiquated.
Since Fortran 90 the name has been Fortran, not FORTRAN with all caps.
As for which version is used in the wild, it's the same as with many other languages that have stuck around for a long time. Plenty of legacy code which might still be F77, but practically all new projects, or extensive modernization of legacy code, will make use of the modern features.
I suspect Fortran's reputation is largely due to many of the foundational libraries of numerical computing like BLAS and LAPACK, are F77 (LAPACK uses a small number of 'modern' features, but largely it's still a F77 codebase). This is the kind of Fortran that non-Fortran programmers might come into contact with. But the Fortran that Fortran programmers write today is definitely much more modern.
That's not my point. My point is that if a modern FORTRAN exists and almost no one uses it, then the reputation for FORTRAN for not being modern is justified because most people that will work with it will work with the old version.
-But we can build with concrete and steel and plastics and all sorts now.
-Most people use bricks though. And people are not tearing their brick houses down to rebuild them in steel. See? Building is old fashioned, antiquated!
In fact, nobody now starts a new project in F77. There’s a lot of F77 brick code around, yes. And it still does the job it was asked to do even though it gets moved to a new district every ten years.
That sounds like a strawman. You're ignoring maintenance and adding features to old codebases. It's usually the majority of the work done. Sure, you don't need to recode BLAS as it's doing its job. But not everything is BLAS.
I am sitting here looking at a 50-line Fortran routine in our codebase that says
! MARK 1 RELEASE. NAG COPYRIGHT 1971.
It has been revised since then to use free form, structured programming, MODULEs, KINDs, INTENTs and IMPLICIT NONE.
If we can do it, everybody can. I have already mentioned some reasons that people don't do it. None of the reasons I have heard are "Fortran is too old and clunky".
Considering that most Java codebases are still on Java 8, I'm not sure I agree with your point that "If we can do it, everybody can". Let's agree to disagree on that.
And there is the "intersection format" http://fortranwiki.org/fortran/show/Continuation+lines that use a careful placement and combination to make the code legal in the fixed and free format. It's useful when your coworkers have a lot of old code and refuse to modernize it, and you want to at least make the new code nice.
For current information on Fortran one should visit https://fortran-lang.org/ .