Asked  11 Months ago    Answers:  5   Viewed   184 times

I understand gfortran can compile f90 or f95? How does it know which one it is compiling? Also can it compile f77 code? Does ubuntu already have a fortran compiler or do I need to download gfortran?



gfortran can guess certain things from the file extension; if the file has an extension of .f, .f90, f95, .f03, or .f08 it will assume fixed (.f) or free format with the appropriate standards. But you can force it to compile (say) fortran2003 code with the option -std=f2003. Eg, from the documentation,


Specify the standard to which the program is expected to conform, which may be one of f95, f2003, f2008, f2018, gnu, or legacy. The default value for std is gnu, which specifies a superset of the latest Fortran standard that includes all of the extensions supported by GNU Fortran, although warnings will be given for obsolete extensions not recommended for use in new code. The legacy value is equivalent but without the warnings for obsolete extensions, and may be useful for old non-standard programs. The f95, f2003, f2008, and f2018 values specify strict conformance to the Fortran 95, Fortran 2003, Fortran 2008 and Fortran 2018 standards, respectively; errors are given for all extensions beyond the relevant language standard, and warnings are given for the Fortran 77 features that are permitted but obsolescent in later standards. -std=f2008ts allows the Fortran 2008 standard including the additions of the Technical Specification (TS) 29113 on Further Interoperability of Fortran with C and TS 18508 on Additional Parallel Features in Fortran.

Note that, with a few exceptions, the fortran standards are highly backwards-compatable, so that much "nice", standard conforming, fortran-77 code is also valid fortran 2003 code. The main problem with that is that much fortran code from the 80s and earlier is neither "nice" nor standard-conforming.

Wednesday, July 28, 2021

The simplest, and best long-term solution, is to use BuildConfig.DEBUG. This is a boolean value that will be true for a debug build, false otherwise:

if (BuildConfig.DEBUG) {
  // do something for a debug build

There have been reports that this value is not 100% reliable from Eclipse-based builds, though I personally have not encountered a problem, so I cannot say how much of an issue it really is.

If you are using Android Studio, or if you are using Gradle from the command line, you can add your own stuff to BuildConfig or otherwise tweak the debug and release build types to help distinguish these situations at runtime.

The solution from Illegal Argument is based on the value of the android:debuggable flag in the manifest. If that is how you wish to distinguish a "debug" build from a "release" build, then by definition, that's the best solution. However, bear in mind that going forward, the debuggable flag is really an independent concept from what Gradle/Android Studio consider a "debug" build to be. Any build type can elect to set the debuggable flag to whatever value that makes sense for that developer and for that build type.

Monday, June 7, 2021

You have some lengths 12 in the constructor, so it may be better to use length 12.

Also, use instead

character(len=12), dimension(5) :: models = [character(len=12) :: "feddes.swp", &
                "jarvis89.swp", "jarvis10.swp", "pem.swp", "van.swp"]

Possibly even better, if you have compiler support, is

character(len=*), dimension(*) :: ...
Friday, June 25, 2021

This code has a few problems, perhaps caused by misunderstandings around the language. These problems have nothing to do with the specific compiler - the code itself is broken.

Conceptually, note that:

  • There is one and only one instance of a saved variable in a procedure per program in Fortran 90.
  • The variable representing the function result always starts off undefined each time a function is called.
  • If you want a pointer in a calling scope to point at the result of a function with a pointer result, then you must use pointer assignment.
  • If a pointer is allocated, you need to have a matching deallocate.

There is a latent logic error, in that the saved first_entry variables in the getX and setX procedures are conflated with object specific state in the setX procedure and procedure instance specific state in the getX procedure.

The first time setX is ever called the x pointer component of the particular this object will be nullified due to the if statement (there's an issue of poor style there too - be careful having multiple statements after an if statement - it is only the first one that is subject to the conditional!). If setX is then called again with a different this, first_entry will have been set to false and the this object will not be correctly set-up. I suspect you are supposed to be testing this%TFX instead.

Similarly, the first time getX is called the otherwise undefined function result variable res will be nullified. However, in all subsequent calls the function result will not be nullified (the function result starts off undefined each execution of the function) and will then be erroneously used in an associated test and also perhaps erroneously in a deallocate statement. (It is illegal to call associated (or deallocate for that matter) on a pointer with an undefined association status - noting that an undefined association status is not the same thing as dissociated.)

getX returns a pointer result - one that is created by the pointer being allocated. This pointer is then lost because "normal" assignment is used to access the value that results from evaluating the function. Because this pointer is lost there can't be (and so there isn't...) a matching deallocate statement to reverse the pointer allocation. The program therefore leaks memory. What almost certainly should be happening is that the thing that captures the value of the getX function in the main program (f in this case, but f is used for multiple things, so I'll call it f_ptr...) itself should be a pointer, and it should be pointer assigned - f_ptr => getX(f1). After the value of f_ptr has been used in the subsequent setX call and write statement, it can then be explicitly deallocated.

The potential for accidental use of normal assignment when pointer assignment is intended is one of the reasons that use of functions with pointer results is discouraged. If you need to return a pointer - then use a subroutine.

Fortran 95 simplifies management of pointer components by allowing default initialization of those components to NULL. (Note that you are using default initialization in your type definition - so your code isn't Fortran 90 anyway!)

Fortran 2003 (or Fortran 95 + the allocatable TR - which is a language level supported by most maintained compilers) introduces allocatable function results - which remove many of the potential errors that can otherwise be made using pointer functions.

Fortran 95 + allocatable TR support is so ubiquitous these days and the language improvements and fixes made to that point are so useful that (unless you are operating on some sort of obscure platform) limiting the language level to Fortran 90 is frankly ridiculous.

Saturday, August 21, 2021

Luajit extends the standard library with a jit module. That is probably a more direct way to detect its presence:

if type(jit) == 'table' then
   print(jit.version)  --LuaJIT 2.0.2
Sunday, December 19, 2021
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :