You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -25,7 +25,7 @@ Wait... Fortran is unable to multiply two integer numbers?? Of course not... The
25
25
26
26
Implicit typing is as old as Fortran, in times where there was no explicit typing. Although it can still be convenient for quickly writing some test code, this practice is highly error prone and is discouraged. The strongly recommended good practice is to always disable implicit typing by stating `implicit none` (introduced in Fortran 90) at the beginning of all program units (main program, modules, and standalone routines):
@@ -45,7 +45,7 @@ Error: Symbol 'nbofchildrem' at (1) has no IMPLICIT type; did you mean 'nbofchil
45
45
Implied save
46
46
------------
47
47
48
-
```
48
+
```{play-code-block} fortran
49
49
subroutine foo()
50
50
implicit none
51
51
integer :: c=0
@@ -64,7 +64,7 @@ implicit none
64
64
end program
65
65
```
66
66
People used to C/C++ expect this program to print 5 times `1`, because they interpret `integer :: c=0` as the concatenation of a declaration and an assignment, as if it was:
67
-
```
67
+
```fortran
68
68
integer :: c
69
69
c = 0
70
70
```
@@ -77,19 +77,19 @@ c = 0
77
77
5
78
78
```
79
79
`integer :: c=0` is actually a one-shot **compile time initialization**, and it makes the variable persistent between calls to `foo()`. It is actually equivalent to:
80
-
```
80
+
```fortran
81
81
integer, save :: c=0 ! "save" can be omitted, but it's clearer with it
82
82
```
83
83
The `save` attribute is equivalent to the C `static` attribute used inside a function to make a variable persistent, and it is *implied* in the case the variable is initialized. This is a modernized syntax (introduced in Fortran 90) compared to the legacy (and still valid) syntax:
84
-
```
84
+
```fortran
85
85
integer c
86
86
data c /0/
87
87
save c
88
88
```
89
89
Old fortraners just know that the modernized syntax is equivalent to the legacy one, even when `save` is not specified. But as a matter of fact the *implied save* can be misleading to newcomers who are used to the C logic. That's why it is generally recommended to **always** specify the `save` attribute.
90
90
91
91
*Note: an initialization expression of a derived type component is a fully different case:*
92
-
```
92
+
```fortran
93
93
type bar
94
94
integer :: c = 0
95
95
end type
@@ -101,7 +101,7 @@ Floating point literal constants
101
101
---------------------------------
102
102
103
103
The following code snippet defines a double precision constant `x` (which is on most systems a IEEE754 64 bits floating point, with 15 significant digits):
104
-
```
104
+
```{play-code-block} fortran
105
105
program foo
106
106
implicit none
107
107
integer, parameter :: dp = kind(0d0)
@@ -116,7 +116,7 @@ The output is:
116
116
So, `x` has 15 significant digits as expected, and still the printed value is wrong from the 8th digit. The reason is that floating point literal constants have implicitely the default real kind, wich is usually the IEEE754 single precision floating point (with about 7 significant digits). The real number $9.3$ has no exact floating point representation, so it is first approximated to single precision up to the 7th digit, then casted to double precision before being assigned to `x`. But the previously lost digits are obviously not recovered.
117
117
118
118
The solution is to explicitly specify the kind of the constant:
119
-
```
119
+
```fortran
120
120
real(kind=dp), parameter :: x = 9.3_dp
121
121
```
122
122
And now the output is correct up to the 15th digit:
@@ -128,7 +128,7 @@ Floating point literal constants (again)
128
128
---------------------------------
129
129
130
130
Suppose now you need a floating point constant that is 1/3 (one-third). You may write:
131
-
```
131
+
```{play-code-block} fortran
132
132
program foo
133
133
implicit none
134
134
integer, parameter :: dp = kind(0d0)
@@ -143,7 +143,7 @@ Then the output is (!):
143
143
The reason is that `1_dp` and `3_dp` are **integer** literal constants, despite the `_dp` suffix that is *supposed* to represent a floating point kind. Consequently the division is the integer division, with 0 as a result. The gotcha here is that the standard allows compilers to use identical kind values for `REAL` and `INTEGER` types. For instance with gfortran, on most platforms the value $8$ is both the double precision kind AND the 64 bits integer kind, so that `1_dp` is a fully valid integer constant. In constrast, the NAG compiler uses by default unique kind values, such that in the example above `1_dp` would produce a compilation error.
144
144
145
145
The right way to denote floating point constants is to **always** include the point:
146
-
```
146
+
```fortran
147
147
real(dp), parameter :: onethird = 1.0_dp / 3.0_dp
148
148
```
149
149
Then the ouput is:
@@ -154,23 +154,23 @@ Then the ouput is:
154
154
Leading space in prints
155
155
-----------------------
156
156
157
-
```
157
+
```{play-code-block} fortran
158
158
program foo
159
159
implicit none
160
160
print*, "Hello world!"
161
161
end program
162
162
```
163
163
Ouput:
164
-
```
164
+
```console
165
165
% gfortran hello.f90 && ./a.out
166
166
Hello world!
167
167
```
168
168
Note the extra leading space, which is not present in the string of the source code. Historically, the first character was containing a [carriage control code](https://en.wikipedia.org/wiki/ASA_carriage_control_characters) for the early printers, and it was not printed per se. The space " " was instructing the printer to perform a CR+LF sequence before printing the content, and was automatically prepended by the Fortran `print*` statement. Some compilers still do that, although the modern output devices do neither intercept nor use the control character, which is hence "printed". If this leading blank is a problem (it rarely is), then instead of the `*` (which means "let the compiler decide how to format the output") we can code an explicit format:
169
-
```
169
+
```fortran
170
170
print "(A)", "Hello world!"
171
171
```
172
172
In this case, the compiler does no longer prepend the leading space:
173
-
```
173
+
```console
174
174
% gfortran hello.f90 && ./a.out
175
175
Hello world!
176
176
```
@@ -179,7 +179,7 @@ Filename extension
179
179
------------------
180
180
181
181
Suppose we put the above "Hello world" program in the source file `hello.f`. Most compilers will produce many compilation errors:
Copy file name to clipboardExpand all lines: source/learn/quickstart/organising_code.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -176,7 +176,7 @@ use my_mod, only: printMat=>print_matrix
176
176
177
177
An advantage of placing subroutines and functions in modules is that they can have ```optional``` arguments. In a procedure with an argument declared optional, the ```present``` function is used to test if the argument was set in the caller. Optional arguments that are not present may not be accessed within the procedure. Here is a generalization of the ```vector_norm``` function that can use powers other than 2 to compute the Lp norm.
0 commit comments