ZetCode

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.

kinds.f90
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.

abs1.f90
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.

round1.f90
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.

conv.f90
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.

math1.f90
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.

trig.f90
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.

atan2demo.f90
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.

hyp.f90
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.

inq.f90
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.

distance.f90
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

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Fortran tutorials.