Fortran Tutorial:
https://fortran-lang.org/en/learn/os_setup/
Fortran 90/95 reference:
https://icl.utk.edu/~mgates3/docs/fortran.html#Loops
Multiple Precision Computation: http://dmsmith.lmu.build/
Fortran Package Manager:
https://fpm.fortran-lang.org/index.html
Fortran Package Manager and OpenMP:
https://www.openmp.org/blog/fortran-package-manager-and-openmp/
Using MPI with Fortran:
https://curc.readthedocs.io/en/latest/programming/MPI-Fortran.html
Fortran terminal I/O, the ISO standard way:
https://www.scivision.dev/fortran-terminal-io
print vs write Fortran statements:
https://www.scivision.dev/print-vs-write-fortran/

! built-in data types
* integer - for data that represent whole numbers, positive or negative
* real - for floating-point data (not a whole number)
* complex - pair consisting of a real part and an imaginary part
* character - for text data
* logical - for data that represent boolean (true/false) values

! variable declaration
integer :: n
real :: pi
complex :: freq
character :: char
logical :: option

! variable assignment
n = 100
pi = 3.1415927
freq = (1.0, -0.5)
char = 'A'
option = .true.

! built-in numeric type kinds in iso_fortran_env
Type kind           Type                Size(bytes)             C-equivalent
---------------------------------------------------------------------------------------
int8                integer             1                       None
int16               integer             2                       short
int32               integer             4                       int
int64               integer             8                       long
real32              real, complex       4                       float
real64              real, complex       8                       double
real128             real, complex       16                      long double

! operators
Operator                Description                         Examples
---------------------------------------------------------------------------------------
**                      exponent                            a**b
*                       multiply                            a*b
/                       divide                              a/b
+                       add                                 a + b
-                       subtract                            a - b
//                      string concatenation                "foo" // "bar"
<       .lt.            less than                           a < b
<=      .le.            less than or equals                 a <= b
>       .gt.            greater than                        a > b
>=      .ge.            greater than or equals              a >= b
==      .eq.            equals                              a == b
/=      .ne.            not equals                          a /= b
        .not.           logical not (unary)                 .not. a
        .and.           logical and                         a .and. b
        .or.            logical or                          a .or. b
        .eqv.           logical = equals                    a .eqv. b
        .neqv.          xor, logical /= not equals          a .neqv. b

! pi value
pi = acos(-1.0)     /* better/faster than pi = 4*atan(1.0) */

! function that returns a sum of two integers
function sum(a, b)
    integer, intent(in) :: a, b
    integer :: sum

    sum = a + b
end function sum

! specifying the data type of the function result in the function statement
integer function sum(a, b)
    integer, intent(in) :: a, b
    sum = a + b
end function sum

! specifying the function result as different from the function name
integer function sum(a, b) result(res)
    integer, intent(in) :: a, b
    res = a + b
end function sum

! using mpi with fortran  [curc.readthedocs.io/en/latest/programming/MPI-Fortran.html]
$ mpif90 program.f90 -o program     /* gnu fortran compiler */
$ mpiexec -n 4 ./program

! initializing an array
integer, allocatable :: a(:)
integer :: i
a = [(i, i = 1, 100)]   /* elements will range from 1 to 100 */

! initializing a real array with sines from 0 to 2pi, with 1000 steps
real, allocatable :: a(:)
integer :: i
real, parameter :: pi = 3.14159256
a = [(sin(2*pi*i/1000.), i = 0, 1000)]  /* an array with sines from 0 to 2pi*/

! initializing an array of a thousand zeros
integer, allocatable :: a(:)
integer :: i
a = [(0, i = 1, 1000)]

! ternary operator
if-else statement:
    if (a > b) then
        x = a
    else
        x = b
    endif

ternary statement:
x = merge(a, b, a > b) /* variable = merge(value if true, value if false, condition) */

! disassemble fortran executables
$ gfortran program.f90 -o program
$ objdump --disassemle program > program.s

! descriptor symbols
The common descriptor symbols are
    * 'd' - number of digits to the right of decimal place of a real
    * 'm' - minimum number of 'digits' to be displayed
    * 'n' - number of spaces to skip
    * 'r' - Repeat Count no. of times a descriptor is to be repeated
    * 'w' - Field Width number of characters wide to use for date

Integer: rIw.m
print "(3I6)", i, j, k
which would print each of the 'Integers' i, j and k in fields of width 6 characters

Real: rFw.d
print "(F12.3)", pi
which would print the constant 'pi' in a field of width 12 characters with 3 decimal
places

Real: rEw.d
print "(E10.3)", 123456.0
which gives '0.123E+06'

Real: rESw.d
print "(ES10.3)", 123456.0
which gives '1.235E+05'

Character: rAw
print "(A10)", str
which would print out the character string 'str' in a field width of 10 characters

Space: nX ('n' is the number of desired spaces)
print "(5X, A10)", str
which would print out 5 blank spaces then the character string 'str' in a field width
of 10 characters

Newline: /
print "(/,5X, A10)", str
which would print out a blank line then 5 blank spaces then the character string 'str'
in a field width of 10 characters

Note: descriptor statements are separated with commas in the format string
