With LLMs, should Fortran have more built-in procedures and delete more legacy features?

There is also the basic question of whether the operation should be done by a function or by a subroutine. My versions of these subprograms are subroutines, and they operate on the argument in-place, without any stack or heap allocation internally. A function interface, in contrast, always requires memory allocation, which can be relatively expensive compared to the case conversion operation itself. On the other hand, the function interface can be used in expressions, possibly invoking several such functions in the same statement, so it can be more convenient. Or there can be both interfaces provided, a subroutine that does the work efficiently, and a function that allocates its memory and then invokes the subroutine. Then the programmer can choose which compromise is best.

To give a practical example, there is an intrinsic function matmul(), but there is no intrinsic subroutine interface to perform a matrix-matrix product. There is no native fortran matmul() implementation that performs as well as the BLAS routines sgemm() or dgemm(). That poor design choice results in a practical dilemma that should have never occurred, much less that has persisted for some 35 years.

Locating the procedures and how to use them(even having them available somewhere publicly) is definitely a hurdle. As mentioned, that is something extremely common in C. Some vendors have improved that situation by finally making sure man-pages have working examples with include statements shown; but ideally the language should avoid that and I admit I really like just calling common math functions without having to do any setup. I just think there are so many functions that should be available in a standard manner that adding them directly as intrinsics would be overwhelming for the standards committee and would slow down coarray development and improved C interfacing and other functionallity that can only be added to Fortran at the base level (although the standard C interface allows for using components from other languages in some cases). I think a modular process is more sustainable as it allows for the user community to try out different versions, let most development proceed sans the Fortran committee (in a good way) , provide optimized versions (sadly a lot of intrinsic functions seem to not be optimized, whereas in early Fortran implementations I could generally depend on it being hard to beat the performance or robustness of intrinsics, that is often not the case anymore). But even the intrinsics that are available are sometimes not used because of ignorance of their existence. An fpm package repository seems to be stagnant (?) but seems like a good approach that would make using the packages reliable enough to be depended upon. A new vetted “netlib” better structured and actively maintained is needed.

The proposal and development and competitive stages should be separate from the stdlib and Fortran standard as much as possible to keep things workable. The project to improve the visibility and searchability of the packages on fortran-lang is a step forward, but package repositories seem much more active in rust, d, python, …

A standard deviation function may be called sd, std (used in stdlib), stdev, std_dev etc.

I would count those as “one” function for the purpose of including in the standard.

It is an interesting question as to what should be an intrinsic procedure. Their generic attribute is friendly.
I expect there are many different views on this ! It depends on your field of study.

I have never used gamma or bessel functions, or sinpi ( lots of advances here for a narrow group? )

I am always writing functions clock_seconds and delta_seconds and always wanting processor_clock_ticks.
I have long needed available_physical_memory, available_virtual_memory and size_in_bytes for derived type data structures (why bits?), although these were more necessary when there was much less available memory. ( I wonder how available_stack_size might be used ?)

std_dev is interesting, as is it std_dev.p or std_dev.s ?

Should Fortran extend random_number to provide Normal and Poisson distributions by name ?
Those who need them have them already, but a generic function is nice.

I personally do a lot of interfacing with .csv files, although I have to reinvent this library many times for different data attributes.

It depends on your field of study!

1 Like

I think it is to accommodate sizes in bits not divisible by 8. I don’t know if that would (in the future) apply to 4bit floats and various other reduced precision numbers used in AI a lot.

I have wanted a standard syntax for those memory-queries too, for some four decades. Back then, we had to do our own memory management within f77. Then f90 introduced allocate/deallocate and automatic arrays, which made some things simpler, but if you want to manage, say your total memory usage, or to dynamically choose which code branch to take depending on the available memory, those new features became obstacles, not conveniences, to your goal.

As for bits rather than bytes, I think that is easy. Much fortran programming in the 1960s through the 1980s was done on machines that were word addressable, not byte addressable. It might have even been the majority of scientific, engineering, and numerical programming at that time, but if not, then at least a significant fraction. These included all of the CDC machines, FPS machines, and the Cray machines of that time. Even some IBM mainframes and Univac machines used hardware with 36-bit words, not bytes. Anyone having to spend time porting byte-oriented codes to these word machines would wonder how those authors could be so thoughtless, or so malicious, to program that way. Even now, in the 21st century, I’m reluctant to use a byte-oriented method to solve problems that can just as easily be solved otherwise. You know, just in case word-addressable machines become popular again! :wink:

My general feeling is that if there is anything that can crash your program, such as exhausting stack space, then the programmer should have the ability to query it in advance. That gives the programmer the ability to do a graceful exit, or to modify his algorithm to fit into the available space, or to change the code branch entirely to solve the problem a different way. The programmer should never be blindfolded and held hostage by the hardware, the language should at least allow him to see enough of the hardware to avoid capture.

I guess it depends on how portable is the user code to solve these problems. If the user code depends on the underlying hardware, say floating point precision or big/little-endian addressing conventions, then it can be difficult to write portable fortran code, especially without a standard preprocessor to allow conditional compilation. So in these cases, a standard intrinsic is useful. It only needs to be written once by the compiler author, and used millions of times, rather than be rewritten millions of times by each programmer.

As for generic interfaces, those were not available to fortran programmers for user codes prior to f90. One might argue that the current mechanism is rather awkward, but at least it is available now. And there is ongoing activity to make it easier to write such codes. Ironically, one of the main reasons this is important was the need to change subroutine names when moving between byte-oriented and word-oriented machines. I used to have a separate conversion utility that would convert between SAXPY and DAXPY, SDOT and DDOT, and so on for my codes when moving back and forth in the f77 days. That problem is still there even today with LAPACK (and other) library naming conventions, it is just less obvious now because word-addressable machines are less common.

Everyone has used spreadsheets over the last 30 to 40 years, so the ability to read, write, and modify spreadsheet files should have been standardized long ago. I would say both in csv form and in standard form. If not as part of the fortran standard, then at least as a de facto standard utility.

I think the same can be argued for a standard way to create graphics images from fortran (at least line plots, but maybe now in the 21st century even beyond, to animations). This should have been done long ago.

By definition, these machines were addressing bytes, as a common definition for “byte” is “the smallest addressable unit in a computer’s architecture”. It’s just that bytes happened to be 36 bits on some machines.

Jane and I have written a small set of examples using the Windows and Linux memory api’s.

Here is the main program for one of examples using the Windows memory api’s.

#####

include ‘integer_kind_module.f90’
include ‘display_with_commas_module.f90’
include ‘memory_module_windows.f90’

program ch4401

use iso_fortran_env
use memory_module_windows
use display_with_commas_module

print *,compiler_version()
print *,’ Memory usage ‘,MemoryLoad(),’ %’
print *,’ Total physical ‘,display_with_commas(TotalPhysical())
print *,’ Available physical ‘,display_with_commas(AvailablePhysical())
print *,’ Total page file ‘,display_with_commas(TotalPageFile())
print *,’ Available page file ‘,display_with_commas(AvailablePageFile())
print *,’ Total virtual ‘,display_with_commas(TotalVirtual())
print *,’ Available virtual ',display_with_commas(AvailableVirtual())

end program ch4401

#####

Here is the main program for one of examples using the Linux memory api’s.

#####

include ‘integer_kind_module.f90’
include ‘ch4402_memory_module_linux.f90’
include ‘display_with_commas_module.f90’

program ch4402

use iso_fortran_env
use memory_module_linux
use display_with_commas_module

print *,compiler_version()
print *,’ Total ram ‘,totalram() ,’ ‘,display_with_commas(totalram())
print *,’ Free ram ‘,freeram() ,’ ‘,display_with_commas(freeram())
print *,’ Share ram ‘,sharedram() ,’ ‘,display_with_commas(sharedram())
print *,’ Buffer ram ‘,bufferram() ,’ ‘,display_with_commas(bufferram())
print *,’ Total swap ‘,totalswap() ,’ ‘,display_with_commas(totalswap())
print *,’ Free swap ‘,freeswap() ,’ ‘,display_with_commas(freeswap())
print *,’ Total high ‘,totalhigh() ,’ ‘,display_with_commas(totalhigh())
print *,’ Free high ‘,freehigh() ,’ ',display_with_commas(freehigh())
end program ch4402

#####

The complete source code can be found at our web sites.

A tar file is available on this site of all of the source code.

Here is some sample out from the Intel ifx compiler under Windows

Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2026
.0.0 Build 20260331
Memory usage 13 %
Total physical 137,131,782,144
Available physical 117,936,807,936
Total page file 157,532,876,800
Available page file 137,739,665,408
Total virtual 140,737,488,224,256
Available virtual 140,733,140,942,848

Here is some sample output from the gfortran compiler under Linux.

ian@dell-5820:/mnt/c/document/fortran/4th_edition_update/examples> ./ch4402_gfortran.out
GCC version 15.2.1 20260202
Total ram 84329304064 84,329,304,064
Free ram 83532967936 83,532,967,936
Share ram 3108864 3,108,864
Buffer ram 44003328 44,003,328
Total swap 21474836480 21,474,836,480
Free swap 21474836480 21,474,836,480
Total high 0 0
Free high 0 0
ian@dell-5820:/mnt/c/document/fortran/4th_edition_update/examples>

examples ch4405.f90 (Windows) and ch4406.f90 (Linux) illustrate checking memory availability and terminating gracefully.

1 Like

I have sometimes used Bessel and gamma functions but the intrinsic ones do not (yet?) provide them for complex arguments.

1 Like