Fortran, APL

a side-by-side reference sheet

grammar and invocation | variables and expressions | arithmetic and logic | strings | dates and time | arrays | arithmetic sequences | functions | execution control | file handles | processes and environment

vectors | matrices

fortran apl
version used
 
GNU Fortran 4.5 (Fortran 95) GNU APL 1.5
show version
 
$ gfortran --version $ apl --version
grammar and invocation
fortran apl
hello word $ cat hello.f95
program hello
  write(*,*) 'Hello, World!'
end program hello

$ gfortran hello.f95

$ ./a.out
 Hello, World!
$ cat hello.apl
"Hello, World!"
)OFF

$ apl --script --noSV -f hello.apl
Hello, World!
file suffixes
source, header, object file
.f95 none .o
block delimiters program end program
function end function
subroutine end subroutine
if then elseif then else endif
do while end do
do end do
statement terminator newline

when a line ends with & the statement continues on the following line
end-of-line comment ! comment comment

the standard name foris "lamp"
multiple line comment none
variables and expressions
fortran apl
are identifiers case sensitive no; Fortran 77 and earlier required all caps yes
variable types integer real complex character logical
variable declaration integer :: n
real :: x = 3.7
! variable declarations must appear before
! all other statements in a program or function body
undeclared variable type inferred from first letter of name:

  I-N: integer
  A-H, O-Z: real
declare primitive type on stack integer::i
integer::j = 3
assignment i = 3 ⍝ leftarrow: ←

i ← 3
null
 
used for pointers only:
null()
undefined variable access evaluate to 0 or 0.0, depending upon the first letter of the variable name VALUE ERROR
arithmetic and logic
fortran apl
boolean type
 
logical all values have same type
true and false
 
.true. .false. 1 0
falsehoods
 
.false.
no implicit conversion of values to booleans
0 0.0
logical operators .and. .or. .not. ⍝ and: ∧
⍝ or:  
⍝ not: ~


∧ ∨ ~
relational operators
 
== /= > < >= <= ⍝ match:   
⍝ unequal: ≠
⍝ aft:     
⍝ fore:    


≡ ≠ > < ≥ ≤
min and max min(1, 2, 3)
max(1, 2, 3)
⍝ minimum: ⌊
⍝ maximum: ⌈


1 ⌊ 2 ⌊ 3
1 ⌈ 2 ⌈ 3

⌊ / 1 2 3
⌈ / 1 2 3
integer type
 
integer

number of bytes can be specified:
integer(kind=4)
all values have same type
integer literal -4 ⍝ macron: ¯

¯4
float type real
double precision

number of bytes can be specified:
real(kind=4)
all values have same type
arithmetic operators
 
+ - * / ⍝ times: ×
⍝ per:   ÷

+ - × ÷
integer division 7 / 3
mod(7, 3)
integer division by zero real :: x = 0.0
integer :: i = 0

! compiler error:
1.0 / 0.0

! +Infinity:
1.0 / x

! floating point exception:
1 / i
DOMAIN ERROR
float division
 
3 / float(7) 3 ÷ 7
float division by zero real :: x = 0.0
integer :: i = 0

! compiler error:
1.0 / 0.0

! +Infinity:
1.0 / x

! floating point exception:
1 / i
DOMAIN ERROR
power 2.0 ** 3.0 2 * 32
sqrt sqrt(2) 2 * 0.5
sqrt -1 real :: x = -1.0
complex :: z = (-1.0, 0.0)

! compiler error:
sqrt(-1.0)

! NaN:
sqrt(x)

! (0.000, 1.000)
sqrt(z)
⍝ 0J1:

¯1 * 0.5
transcendental functions exp(2.0)
log(2.0)
log10(2.0)
sin(2.0)
cos(2.0)
tan(2.0)
asin(0.5)
acos(0.5)
atan(0.5)
atan2(1.0, 2.0)
⍝ log:    
⍝ circle: ○


* 2
⍟ 2
10 ⍟ 2
1 ○ 2
2 ○ 2
3 ○ 2
¯1 ○ 0.5
¯2 ○ 0.5
¯3 ○ 0.5
??
transcendental constants
e and pi
exp(1.0)
2.0 * asin(1.0)
* 1
○ 1
float truncation
truncate, round, ceiling, floor
int(3.7)
none
ceiling(3.7)
floor(3.7)
??
??
⌈ 3.7
⌊ 3.7

⍝ ceiling: ⌈
⍝ floor: ⌊
absolute value abs(-7)
abs(-7.77)
| ¯7
| ¯7.77
complex type complex

uses 8 bytes:
complex(kind=4)
all values have same type
complex construction (0.0, 1.0)
(0.0, 2.0)
(0.0, 3.0)
0J1
0J2
0J3
complex decomposition
real and imaginary component, argument, absolute value, conjugate
real(z)
imag(z)
atan2(imag(z), real(z))
abs(z)
conjg(z)
z ← 3J2

(z + + z) ÷ 2
| (z - + z) ÷ 2
??
| z
+ z
random number real r
! random float from 0.0 to 1.0:
call random_number(r)
⍝ random integer from 1 to 100:
? 100
random seed integer n
integer, allocatable :: seed(:)

call random_seed(size=n)
allocate(seed(n))
do i = 1, n
  seed(i) = i + 2
end do
call random_seed(put=seed)
⎕RL ← 17
bit operators right shift if pos is positive:
ishft(i, pos)
iand(i, j)
ior(i, j)
ieor(i, j)
not(i)
strings
fortran apl
string type
 
characater(len=100) s
string literal
 
'don''t say "no"'
"don't say ""no"""
'don''t say "no"'
newline in string literal "lorem" // achar(10) // "ipsum"
string escapes none
convert string to numeric ⍝ execute: ⍎

⍎ '4'
convert numeric to string
split none
join
 
, / 'foo' 'bar' 'baz'
concatenate 'hello' // ' world' 'hello' , ' world'
replicate character(len=80) :: hbar
hbar = repeat('-', 80)
substring "hello"(1:4)
index counts from one, returns zero if not found
index("hello", "el")
sprintf character(len=100) :: s
write(s,'(A A F9.3 I9)') 'foo', ':', 2.2, 7
uppercase none
lowercase none
trim ??
adjustl(' foo')
trim('foo ')
length
 
len("hello") ⍴ 'hello'
character access "hello"(1:1)
chr and ord achar(65)
iachar('A')
dates and time
fortran apl
current local date and time integer dt(8)

! yyyy, mm, dd, utf_offset_min, hh24, mi, ss, ms
call date_and_time(values=dt)
⍝ array of 7 integers: yyyy, mm, dd, hh24, mi, ss, ms
⎕TS
sleep ! gnu extension; sleep 10s:
call sleep(10)
none
cpu usage real t1, t2
call cpu_time(t1)

call cpu_time(t2)
write(*, *) 'elapsed time: ', t2 - t1
none
arrays
fortran apl
allocate on stack ! uninitialized values get zero values:
integer, dimension(3) :: a
integer :: a2(3)
none
allocate on heap ! unitialized values get zero values:
integer, dimension(:), allocatable :: a
allocate(a(3))
all data is stored on heap
free heap ! usually not necessary, since memory is freed
! when the variable goes out of scope.

deallocate(a)
none; memory is garbage collected
literal integer::a(3) = (/ 1, 2, 3 /) a ← 1 2 3
size
 
size((/ 1, 2, 3 /)) ⍝ rho: ⍴

⍴ a
lookup
 
! indices start at one
integer :: a(4)
a = (/ 7, 8, 9, 10 /)
a(2)
a ← 7 8 9 10

a[2]
(7 8 9 10)[2]

⍝ change index origin from 1 to 0:
⎕IO ← 0
update a(1) = 8 a[1] ← 8
out-of-bounds behavior If the array dimensions are set at compilation time (i.e. the array is stack allocated), then the code fails to compile.

Out-of-bounds references to arrays with dimensions set at run time (i.e. the array is heap allocated) could segfault or return a memory value outside of the array.
INDEX ERROR
element index ⍝ evaluates to 2:
7 8 9 ⍳ 8
slice ! can't slice literal
int::a1(3),a2(2)

a1 = (/1,2,3/)
a2 = a1(1:2)
⍝ 7 8:

a ← 7 8 9 10
1 ↓ 3 ↑ a
slice to end ⍝ 8 9 10:

a ← 7 8 9 10
1 ↓ a
manipulate back a ← 7 8 9 10

⍝ 10:
¯1 ↑ a

⍝ set a to 7 8 9:
a ← ¯1 ↓ a

⍝ set a to 7 8 9 11:
a ← a , 11
manipulate front a ← 7 8 9 10

⍝ 6:
1 ↑ a

⍝ set a to 8 9 10:
a ← 1 ↓ a

⍝ set a to 6 8 9 10:
a ← 6 , a
concatenate 1 2 3 , 4 5 6
replicate ⍝ 10 zeros:
10 / 0
copy a ← 1 2 3
b ← a
⍝ does not modify a:
b[1] ← 4
iterate
sort a ← 8 7 10 9
a[⍋ a]
reduce + / 1 2 3

⍝ 2:
- / 1 2 3
arithmetic sequences
fortran apl
unit difference ⍝ iota: ⍳

⍳ 100
difference of 10 ⍝ 0, 10, ..., 100:

10 × ( ⍳ 11 ) - 1
difference of .1 ⍝ 0.0, 0.1, ..., 10.0

.1 × ( ⍳ 101 ) - 1
functions
fortran apl
define function integer function add(n, m)
  integer, intent(in) :: n
  integer, intent(in) :: m
  add = n + m
end function add
⍝ define dyadic operator:
∇r ← a add b
r ← a + b ∇

⍝ define monadic operator:
∇r ← double n
r ← 2 × n ∇
invoke function
 
add(3, 7) 3 add 7
double 7
forward declaration of function
overload function
nest function
missing argument behavior set to zero
extra argument behavior ignored
default value for parameter real function mylog(x, base)
  real :: x
  real, optional :: base
  if (present(base)) then
    mylog = log(x) / log(base)
  else
    mylog = log(x) / log(10.0)
  endif
end function mylog
variable number of arguments none
named parameters
pass by value
pass by address
pass by reference
return value assign to implicit variable with same name as function; can use return statement to terminate function execution
no return value
multiple return values
named return values
anonymous function literal none
function with private state
function as value none; function pointers added in Fortran 2003
execution control
fortran apl
for do n = 1, 10, 1
  write(*,*) n
end do
if if (n == 0) then
  write(*,*) 'no hits'
elseif (n == 1) then
  write(*,*) 'one hit'
else
  write(*,*) n, 'hits'
endif
while n = 1
do while ( n < 10 )
  write(*,*) n
  n = n + 1
end do
switch
break/continue
 
exit cycle
file handles
fortran apl
standard file handles ! common unit identifiers for stdin, stdout, and stderr:
5 6 0
read line from stdin character(len=100) line

read(*, fmt="(a)") line
write line to stdout write(*, *) 'Hello, World!'
write formatted string to stdout
 
write(6, fmt="('count: ', i7)") 7
open file for reading ! the 'unit' integer is the file descriptor. Use an unused
! number. The standard file handles 0, 5, and 6 are already taken.

open(unit=7, file='/etc/passwd', action='read')
open file for writing open(unit=7, file='/tmp/foo.txt', action='write')
close file close(7)
i/o errors
read line
iterate over file by line
read file into array of strings
read file into string
write string
write line
flush file handle
end-of-file test
 
get and set file handle position
open unused file
processes and environment
fortran apl
command line arguments character(len=10) :: arg
integer arg_len

i = 1
do while (i <= command_argument_count())
  call get_command_argument(i, arg, arg_len)
  if (arg_len > 10) then
    write(*,*) 'truncated argument: ', arg
  else
    write(*,*) 'full argument: ', arg
  endif
  i = i + 1
end do
⎕ARG
environment variable character(len=100) :: var
integer var_len

call get_environment_variable('HOME', var, var_len)
if (var_len > 100) then
  write(*,*) 'truncated env var: ', var
else
  write(*,*) 'full env var: ', var
endif
⍝ quad: ⎕

⎕ENV 'HOME'

⍝ returns n by 2 array containing all environment
⍝ variable names and their values:

⎕ENV ''
exit stop

! nonzero status:
error stop 1
)OFF
vectors
fortran apl
vector literal same as array ⍝ same as array:
1 2 3
element-wise arithmetic operators + - * / + - × ÷
result of vector length mismatch compilation error LENGTH ERROR
scalar multiplication 3 * (/1,2,3/)
(/1,2,3/) * 3
3 × 1 2 3
1 2 3 × 3
dot product dot_product((/1,1,1/),(/2,2,2/)) 1 1 1 + . × 2 2 2
matrices
fortran apl
matrix literal or constructor ! column-major order:
integer::A(2,2) = &
  reshape((/ 1, 3, 2, 4 /), &
  (/ 2, 2 /))

integer::B(2,2) = &
  reshape((/ 4, 2, 3, 1 /), &
  (/ 2, 2 /))
⍝ row-major order:
A ← 2 2 ⍴ 1 2 3 4
constant matrices

all zeros, all ones
3 3 ⍴ 0
3 3 ⍴ 1
diagonal matrices

and identity
⍝ 3×3 identity:
I ← 3 3 ⍴ 1 , 3 ⍴ 0
D ← I + . × 1 2 3
dimensions A ← 2 3 ⍴ 1 2 3 4 5 6

⍴ A
element access A ← 2 2 ⍴ 1 2 3 4
⍝ 1:
A[1; 1]
row access A ← 2 2 ⍴ 1 2 3 4
⍝ 1 2:
A[1; ]
column access A ← 2 2 ⍴ 1 2 3 4
⍝ 1 3:
A[; 1]
scalar multiplication A ← 2 2 ⍴ 1 2 3 4
3 × A
A × 3
element-wise operators + - × ÷
transpose A ← 2 2 ⍴ 1 2 3 4

⍝ cant: ⍉
⍉ A
multiplication matmul(A, B) A ← 2 2 ⍴ 1 2 3 4
B ← 2 2 ⍴ 4 3 2 1
A + . × B
inverse A ← 2 2 ⍴ 1 2 3 4
gray|⍝ inverse: ⌹##
⌹ A
____________________________________________________________________________________________________ ____________________________________________________________________________________________________

Grammar and Invocation

file suffixes

The suffixes used for source files, header files, and compiled object files.

fortran:

The gfortran compiler will treat files with .f and .f77 suffixes as the older fixed format source code, and it will treat files with .f90 and .f95 suffixes as free format source code conforming to the 1990 and 1995 Fortran standards.

Traditionally Fortran does not have header files. The Fortran 90 standard introduced modules. To support the feature the compiler will generate .mod files whenever a source file with a module definition is encountered. They contain type declarations like C headers, but unlike C headers they are not intended to be edited by people.

block delimiters

fortran:

The list of keywords is not exhaustive.

Variables and Expressions

undeclared variable type

fortran:

This makes undeclared variables starting with 'q' integers:

implicit integer q

undefined variable access

fortran:

It is possible to require that all variables are declared:

implicit none

Variable which are declared but not initialized are assigned zero values.

Arithmetic and Logic

boolean type

The boolean type.

true and false

The literals for true and false.

falsehoods

Values which are false in a boolean context.

logical operators

The logical operators for conjunction, disjunction, and negation.

fortran:

.eqv. .neqv.

apl:

APL also has operators for "nand" and "nor":

⍲ ⍱

relational operators

min and max

integer type

integer literal

The syntax for integer literals.

apl:

The minus sign can be used as a unary operator, but applies to the entire array. The following expressions are the same:

- 4 5 6
¯4 ¯5 ¯6

unsigned integer type

Strings

sprintf

fortran:

Fortran format strings use these expressions:

A character
Dwidth.precision double in scientific notation
Ewidth.precision real in scientific notation
Fwidth.precision real in fixed point notation
Iwidth integer
X space
nX repeat following format expression n times
/ newline

width and precision are integers. width is the field width in characters. Other characters in the format string are ignored.

Dates and Time

current local date and time

sleep

cpu usage

Arrays

Arithmetic Sequences

unit difference

difference of 10

difference of 0.1

Functions

Execution Control

break/continue

fortran:

Fortran has a continue statement which is a no-op statement used as a target for goto statements.

Here is an example of using exit to terminate what would otherwise be an infinite loop:

n = 1
do
   if (n > 10) exit
   write(*, *) n
   n = n + 1
end do

Labels can be provided for nested do loops. The labels can be provided as arguments to exit and cycle:

  foo: do
     bar: do n = 1, 10, 1
        write(*,*) n
        exit foo
     end do bar
  end do foo

File Handles

standard file handles

The file handles for standard input, standard output, and standard error.

fortran:

Fortran uses integers which it calls unit identifiers for file descriptors. The unit descriptors 5, 6, and 0 are often but not always used for stdin, stdout, and stderr.

Unit descriptors are provided as the first argument to read and write. If the first argument of read is an asterisk, it will use stdin. If the first argument of write is an asterisk, it will use stdout.

write formatted string to stdout

How to print a formatted string to standard out.

fortran:

Notation used in Fortran format strings.

Processes and Environment

Vectors

Matrices

Fortran

The GNU Fortran Compiler
Fortran 77 Tutorial
Fortran 90 Tutorial
Fortran Standards Documents
BLAS: A Quick Reference Guide (pdf)

Modern Fortran compilers support two source code formats: the traditional fixed format and the free format introduced with Fortran 90.

If a Fortran source file has a .f suffix, the gfortran compiler expects the code to have fixed format. If the suffix is .f90 or .f95 it expects free format code.

Here is an example of fixed format code:

C Hello World
* in Fortran 77

      program hello
10000 write(*,*) 'Hello,'
     + , ' World!'
      end program hello

This first column can contain a 'C', 'c', or '*' to indicate the line is a comment.

Columns 1 through 5 can contain an optional statement label. A statement label consists of digits. The statement label may contain leading zeros which are ignored. A statement label cannot consist entirely of zeros.

If column 6 contains a non-space character and columns 1 through 5 are blank, then the line is treated as a continuation of the previous line. The continuation character is not itself part of the statement, so any non-space character can be used, but '+' is a common choice.

Columns 7 through 72 contain the statement.

Columns 73 through 80 can contain optional sequence numbers. They were formerly used to help keep punch cards in the correct order.

Here is an example of free format code:

! Hello World in Fortran 90

program hello
  write(*,*) 'Hello,' &
       , ' World!'
end program hello

There are no special columns in free format code. There is no limit on the length of lines or statements. If it is desirable to split a statement up over multiple lines, the '&' character can be used to indicate the statement continues on the following line.

APL

A Dictionary of APL
A Programming Language

The first issue one must resolve when getting started with APL is figuring out how to enter the special characters.

One technique is to add a input method to your desktop environment. Here are APL input methods for Mac OS X and Windows. The Windows input method uses AutoHotkey. If you don't have AutoHotkey installed, you can use the .exe file that was generated using AutoHotkey. Otherwise you can use the .ahk file.

The notation in the above input methods is derived from the standard names and synonyms for the symbols in the APL community. The standard name for is "grade". The above input methods use an ampersand prefix in front of the standard name. Thus, to create a character, one types "@grade" when the input method is in effect.

issue tracker | content of this page licensed under creative commons attribution-sharealike 3.0