TYP03-F. Ensure intrinsic function arguments match intended precision
Programmers should use generic intrinsic procedure names and explicitly specify the kind argument for type conversion functions to prevent unintended precision loss.
While modern Fortran provides generic interfaces for most intrinsic procedures, subtle naming conventions and default behaviors can lead to silent data narrowing and numeric errors. Two common mechanisms that cause precision loss are:
- Usage of specific (legacy) intrinsic names. Legacy Fortran required specific function names for different data types (e.g.,
amodfor real,dmodfor double precision). Using a specific name likeamodwith double-precision arguments forces the compiler to convert the arguments to single precision before the operation, discarding significant digits. Calling a mathematical function intended for a smaller data type results in lower-precision operations and loss of information. - Implicit defaults in conversion functions. In Fortran, type conversion functions (specifically
cmplx,real, andint) default to the processor-dependent default kind (usually single precision) regardless of the input precision. This differs from mathematical intrinsics (likesqrtorsin) which automatically inherit the precision of their arguments. If a programmer passes double-precision variables tocmplxwithout akindargument, the data is silently demoted to single precision.
Noncompliant Code Example
In this noncompliant example, the legacy specific intrinsic amod (intended for default real) is used on double-precision variables. The compiler demotes d_val to single precision to satisfy amod , resulting in data loss.
program specific_intrinsic
use iso_fortran_env, only: real64
implicit none
real(real64) :: d_val = 1.23456789012345_real64
real(real64) :: res
! Noncompliant: amod is specific to default real (single precision)
res = amod(d_val, 2.0_real64)
print *, res
end program
Compliant Solution
Using the generic name mod allows the compiler to select the specific procedure that matches the argument's precision.
prprogram generic_intrinsic
use iso_fortran_env, only: real64
implicit none
real(real64) :: d_val = 1.23456789012345_real64
real(real64) :: res
! Noncompliant: MOD is generic and maintains the precision of d_val
res = mod(d_val, 2.0_real64)
print *, res
end program
Noncompliant Code Example
In this noncompliant example, cmplx is called without a kind argument. Even though the inputs are double-precision, the result may be single-precision, leading to truncation and loss of accuracy.
program complex
use iso_fortran_env, only: real64
implicit none
real(real64) :: d_real = 1.23456789012345_real64
real(real64) :: d_imag = 9.87654321098765_real64
complex(real64) :: z
! Noncompliant: CMPLX defaults to single precision
z = cmplx(d_real, d_imag)
print *, z
end program complex
Compliant Solution
By explicitly specifying the kind parameter, cmplx returns a double-precision complex number, preserving the precision of the inputs and preventing silent truncation.
program complex
use iso_fortran_env, only: real64
implicit none
real(real64) :: d_real = 1.23456789012345_real64
real(real64) :: d_imag = 9.87654321098765_real64
complex(real64) :: z
! Compliant: Explicitly specify KIND to preserve double precision
z = cmplx(d_real, d_imag, kind=real64)
print *, z
end program complex
Risk Assessment
Implicit narrowing of function arguments can result in loss of significant digits, which may compound over subsequent calculations and produce numerically incorrect results.
| Recommendation | Severity | Likelihood | Detectable | Repairable | Priority | Level |
| TYP03-F | Low | Probable | Yes | Yes | P6 | L2 |
Bibliography
| [ Fortran 2023 Interpretation Document ] | Section 16.9.53 and 16.9.199 |
Attachments:
button_arrow_left.png (image/png)
button_arrow_up.png (image/png)
button_arrow_right.png (image/png)


