Fortran intrinsic numeric functions
last modified November 14, 2026
Fortran ships with a large set of intrinsic functions, and the numeric ones cover the ground that other languages leave to a maths library: absolute values, rounding, roots, logarithms, trigonometry, and the limits of each floating-point kind. They are part of the language, so no module has to be imported for them, and they are generic: the kind of the result follows the kind of the argument. This article goes through the functions a numerical program uses most, and points out where the result is not what a reader from C would expect.
Generic functions and kinds
Most intrinsic functions are generic, which means that one name accepts
arguments of several types and kinds and returns a value of the matching kind.
sqrt applied to a default real returns a default real, and applied
to a real64 it returns a real64. The same holds for
abs with integers and for sin and the other
trigonometric functions. The exception is nint, which returns a
default integer whatever the kind of its argument.
program kinds
use, intrinsic :: iso_fortran_env, only: int8, int64, real32, real64
implicit none
print *, kind(sqrt(1.0_real32)), kind(sqrt(1.0_real64))
print *, kind(abs(-3_int8)), kind(abs(-3_int64))
print *, kind(sin(0.0_real64))
print *, kind(nint(1.0_real64))
print *, kind(real(1)), kind(real(1, real64))
end program kinds
The square root and the absolute value keep the kind of their argument, so the
first two lines print 4 and 8, and then 1 and 8. The sine of a
real64 is a real64 as well. nint is the
exception: its argument is a real64 but the result is a default
integer of kind 4. The last line shows the conversion function
real, whose optional second argument chooses the kind.
$ gfortran kinds.f90 -o kinds
$ ./kinds
4 8
1 8
8
4
4 8
Absolute value, sign, min and max
abs returns the absolute value of an integer, real or complex
number. sign(a, b) returns the absolute value of a
with the sign of b, and it is the portable way to transfer a sign
without a branch. min and max accept any number of
arguments and return the smallest or largest, with the arguments converted to
a common type first.
program abs1
implicit none
integer :: a, b
real :: x
a = -7
b = 3
x = -2.5
print *, abs(a), abs(x)
print *, sign(a, b), sign(b, a), sign(x, -1.0)
print *, min(a, b), max(a, b)
print *, min(3.0, 2.0, 4.0)
end program abs1
The absolute values are 7 and 2.5. sign(a, b) gives 7 because
b is positive, while sign(b, a) gives -3 because
a is negative. The real version returns -2.5, since the second
argument is negative. The minimum and maximum of -7 and 3 are printed next, and
the last line shows that min accepts three arguments and returns
2.0.
$ gfortran abs1.f90 -o abs1
$ ./abs1
7 2.50000000
7 -3 -2.50000000
-7 3
2.00000000
Rounding to whole numbers
Five functions convert a real to a nearby whole number, and they differ in
whether the result is still real and in which direction they round.
floor rounds down, ceiling rounds up, and both return
an integer. aint truncates toward zero and anint
rounds to the nearest whole number, and both keep the real type.
nint rounds to the nearest integer and returns an integer.
program round1
implicit none
real :: x, y
x = 2.5
y = -2.5
print *, nint(x), nint(y), nint(2.4), nint(2.6)
x = 3.7
y = -3.7
print *, floor(x), ceiling(x), floor(y), ceiling(y)
print *, aint(x), anint(x), aint(y), anint(y)
print *, int(x), int(y)
print *, kind(nint(x)), kind(floor(x))
end program round1
nint rounds halves away from zero, so 2.5 becomes 3 and -2.5
becomes -3, while 2.4 and 2.6 become 2 and 3. floor moves toward
minus infinity and ceiling toward plus infinity, which is why
-3.7 becomes -4 and -3. The third line keeps the real type: aint
truncates to 3.0 and -3.0, and anint rounds to 4.0 and -4.0.
int truncates like aint but returns an integer. Both
integer results have kind 4, including the one from nint on a
default real.
$ gfortran round1.f90 -o round1
$ ./round1
3 -3 2 3
3 4 -4 -3
3.00000000 4.00000000 -3.00000000 -4.00000000
3 -3
4 4
Truncation and conversion
The conversion functions int, real and
cmplx change the type of a value, and an optional second argument
chooses the kind of the result. int truncates toward zero, so it
agrees with aint and not with nint.
real on an integer rounds to the nearest representable value,
which matters only for integers wider than the mantissa. dble is
an older name for a conversion to double precision.
program conv
use, intrinsic :: iso_fortran_env, only: int64, real64
implicit none
real :: x
integer :: i
x = 2.9
i = int(x)
print *, i, nint(x)
print *, int(-2.9), nint(-2.9)
print *, kind(int(x)), kind(int(x, int64))
print *, real(7), real(7, real64)
print *, cmplx(1.0, 2.0)
print *, dble(1.5)
end program conv
Truncating 2.9 gives 2, while rounding gives 3; with the negative value the
difference goes the other way, to -2 and -3. The third line shows the kind
argument of int, which turns a default integer into a 64-bit one.
real converts 7 to 7.0 and, with the kind argument, to a double
precision 7.0. cmplx builds a complex number from its two real
arguments, and dble returns the double-precision form of 1.5.
$ gfortran conv.f90 -o conv
$ ./conv
2 3
-2 -3
4 8
7.00000000 7.0000000000000000
(1.00000000,2.00000000)
1.5000000000000000
Roots, exponentials and logarithms
sqrt takes a real or complex argument, and it does not accept an
integer: sqrt(16) is a compile error, and the smallest fix is
sqrt(16.0). exp computes the exponential, and the
natural logarithm log and the decimal logarithm
log10 are its inverses. Fortran has no built-in logarithm to an
arbitrary base, so it is computed as a quotient of logarithms.
program math1
use, intrinsic :: iso_fortran_env, only: real64
implicit none
real(real64) :: x, e
x = 2.0_real64
e = exp(1.0_real64)
print *, sqrt(x)
print *, exp(x), e ** x
print *, log(e), log10(1000.0_real64)
print *, log(8.0_real64) / log(2.0_real64)
end program math1
The square root of 2 is 1.4142135623730951. exp(x) and
e ** x are two ways to compute the same number, and they differ in
the last digit, because the power is computed through logarithms.
log(e) is 1 and log10(1000) is 3. The last line
computes the base-2 logarithm of 8 as the quotient of two natural logarithms
and gets 3.0.
$ gfortran math1.f90 -o math1 $ ./math1 1.4142135623730951 7.3890560989306504 7.3890560989306495 1.0000000000000000 3.0000000000000000 3.0000000000000000
Trigonometry
The trigonometric functions sin, cos and
tan take an angle in radians, and their inverses
asin, acos and atan return radians.
There is no degree version, so a program converts with the factor
pi / 180. An accurate pi comes from 4 * atan(1.0) in
the kind that the program uses.
program trig
use, intrinsic :: iso_fortran_env, only: real64
implicit none
real(real64), parameter :: pi = 4.0_real64 * atan(1.0_real64)
real(real64) :: angle
angle = pi / 6.0_real64
print *, sin(angle), cos(angle), tan(angle)
print *, asin(0.5_real64), acos(0.5_real64), atan(1.0_real64)
print *, atan2(1.0_real64, 1.0_real64)
print *, atan2(1.0_real64, -1.0_real64) * 180.0_real64 / pi
end program trig
The angle is 30 degrees, so the mathematical sine is 0.5, the cosine is the
square root of three over two, and the tangent is one over the square root of
three. The sine prints as 0.49999999999999994 and not as 0.5, because the
stored angle is not exactly pi/6 and the small error survives the calculation.
The inverse functions return the angles
0.5236, 1.0472 and 0.7854 radians. The last line converts the result of
atan2 for the point (-1, 1), which is 135 degrees.
$ gfortran trig.f90 -o trig $ ./trig 0.49999999999999994 0.86602540378443871 0.57735026918962573 0.52359877559829893 1.0471975511965979 0.78539816339744828 0.78539816339744828 135.00000000000000
The two-argument arctangent
atan2(y, x) returns the angle of the point (x, y) measured from
the positive x axis, in the range from -pi to pi. Unlike atan(y / x)
it uses the signs of both arguments, so it can tell the four quadrants apart
and it does not divide by zero when x is zero.
program atan2demo
use, intrinsic :: iso_fortran_env, only: real64
implicit none
real(real64), parameter :: pi = 4.0_real64 * atan(1.0_real64)
print *, atan2(1.0_real64, 1.0_real64) / pi
print *, atan2(1.0_real64, -1.0_real64) / pi
print *, atan2(-1.0_real64, -1.0_real64) / pi
print *, atan2(-1.0_real64, 1.0_real64) / pi
print *, atan2(0.0_real64, -1.0_real64) / pi
end program atan2demo
The four points on the diagonals give the angles 45, 135, -135 and -45 degrees,
printed as fractions of pi: 0.25, 0.75, -0.75 and -0.25. The last line is the
negative x axis, which is at 180 degrees, and atan2 chooses the
positive pi rather than the negative one. This is the reason to prefer
atan2 in any code that computes a direction from a difference of
coordinates.
$ gfortran atan2demo.f90 -o atan2demo $ ./atan2demo 0.25000000000000000 0.75000000000000000 -0.75000000000000000 -0.25000000000000000 1.0000000000000000
The mod family
mod and modulo work on reals as well as on integers,
and they keep the same rule about the sign: mod follows the
dividend, modulo the divisor. The difference only shows with a
negative argument, which is why a program that only sees positive numbers can
use either.
program hyp
implicit none
real :: a, b
a = 3.0
b = 4.0
print *, sqrt(a * a + b * b), hypot(a, b)
print *, mod(7.5, 2.0), modulo(-7.5, 2.0)
end program hyp
hypot computes the length of the hypotenuse from the two legs
without forming the squares, which avoids overflow for very large values. Here
it agrees with the explicit formula and both give 5.0. The remainders are 1.5
for the positive dividend and 0.5 for the negative one, again because
modulo moves the result toward the sign of the divisor.
$ gfortran hyp.f90 -o hyp $ ./hyp 5.00000000 5.00000000 1.50000000 0.500000000
Numeric inquiry functions
The inquiry functions describe a kind rather than compute with it.
huge returns the largest value, tiny the smallest
positive normal value, and epsilon the difference between 1 and
the next representable number. digits, precision and
range report the mantissa bits, the decimal digits and the
exponent range. Their argument only sets the kind, so the value passed in is
irrelevant.
program inq
use, intrinsic :: iso_fortran_env, only: int32, real32, real64
implicit none
print *, 'default integer: ', huge(1), bit_size(1)
print *, 'int32: ', huge(1_int32)
print *, 'real32 huge: ', huge(1.0_real32)
print *, 'real32 tiny: ', tiny(1.0_real32)
print *, 'real32 epsilon: ', epsilon(1.0_real32)
print *, 'real64 epsilon: ', epsilon(1.0_real64)
print *, 'digits, precision, range:'
print *, digits(1.0_real64), precision(1.0_real64), range(1.0_real64)
end program inq
The default integer is 32 bits wide and holds up to 2147483647, which is
2 ** 31 - 1. A 32-bit real reaches about 3.4e38 and its smallest
normal value is about 1.2e-38. The epsilon of a 32-bit real is 1.19e-7, which
is the precision a single-precision calculation can hope for, and the 64-bit
epsilon is about 2.2e-16. The double-precision real has 53 mantissa bits, 15
decimal digits of precision, and an exponent range of 307.
$ gfortran inq.f90 -o inq
$ ./inq
default integer: 2147483647 32
int32: 2147483647
real32 huge: 3.40282347E+38
real32 tiny: 1.17549435E-38
real32 epsilon: 1.19209290E-07
real64 epsilon: 2.2204460492503131E-016
digits, precision, range:
53 15 307
A complete example
The program below computes the distance and the direction between two points.
The differences of the coordinates are the legs of a right triangle, so the
distance comes from hypot and the direction from
atan2. The angle is converted from radians to degrees before it is
printed.
program distance
use, intrinsic :: iso_fortran_env, only: real64
implicit none
real(real64), parameter :: pi = 4.0_real64 * atan(1.0_real64)
real(real64) :: x1, y1, x2, y2, dx, dy, dist, bearing
x1 = 0.0_real64
y1 = 0.0_real64
x2 = 3.0_real64
y2 = 4.0_real64
dx = x2 - x1
dy = y2 - y1
dist = hypot(dx, dy)
bearing = atan2(dy, dx) * 180.0_real64 / pi
print '(a, f0.3)', 'distance: ', dist
print '(a, f0.3)', 'bearing: ', bearing
end program distance
The legs are 3 and 4, so the distance is 5, which the f0.3 edit
descriptor prints with three decimals as 5.000. The bearing is the
angle whose tangent is 4/3, about 53.13 degrees. The f0.3 form
lets the integer part take as many positions as it needs, which is the usual
way to print a computed real without choosing a total width in advance.
$ gfortran distance.f90 -o distance $ ./distance distance: 5.000 bearing: 53.130
Next steps
Fortran procedures shows how to wrap a
formula such as the one above in a function of your own, and
Fortran operators and expressions describes
the arithmetic in which these functions are used. The kind constants and the
limits behind huge and epsilon are the subject of
Fortran data types and kinds.
Source
GNU Fortran: intrinsic procedures
Fortran 2018 standard (J3/18-007r1), clause 16
In this article we have used the generic numeric intrinsics, taken absolute
values and transferred signs, rounded and truncated reals, converted between
types and kinds, computed roots, exponentials and logarithms, used the
trigonometric functions and atan2, compared the two remainder
functions, asked for the limits of a kind, and computed a distance and a
bearing. The previous article, Fortran loops,
describes the repetition these calculations often run inside.
Author
List all Fortran tutorials.