Description
The function enorm
provides the Euclidean norm of a vector. From the MINPACK user guide:
The algorithm used in
ENORM
is a simplified version of Blue's [1978] algorithm. An advantage of the MINPACK-1 version is that it does not require machine constants; a disadvantage is that nondestructive underflows are allowed.
The function enorm
is obsolescent as far as I'm concerned. The Fortran 2008 standard and later provide a norm2
intrinsic function. The standard recommends that processors compute the result without undue overflow or underflow.
Other notable norm implementations include:
- Original MINPACK
enorm
: https://www.netlib.org/minpack/enorm.f - SLATEC
dnrm2
: https://www.netlib.org/slatec/lin/dnrm2.f - Reference BLAS
dnrm2
: http://www.netlib.org/lapack/explore-3.1.1-html/dnrm2.f.html - Fortran intrinsic function
norm2
: gfortran docs, ifort docs
Here's a quick demonstration program:
program main
implicit none
integer, parameter :: dp = kind(1.0d0)
real(dp) :: x(20)
real(dp) :: dnrm2, enorm
call random_number(x)
print *, "enorm ", enorm(size(x), x)
print *, "dnrm2 ", dnrm2(size(x), x, 1)
print *, "norm2 ", norm2(x)
end program
An example run:
$ gfortran dnrm2.f enorm.f norm_example.f90
$ ./a.out
enorm 2.1356777438951129
dnrm2 2.1356777438951133
norm2 2.1356777438951129
A potential issue of removing enorm
in favor of norm2
are the workarounds needed to support older compilers. One approach could be to use a preprocessor block:
pure real(wp) function enorm(n, x)
integer, intent(in) :: n
real(wp), intent(in) :: x(n)
#if MINPACK1_ENORM
! ... current MINPACK-1 algorithm ...
#else
enorm = norm2(x)
#endif
end function
Personally, I'd just replace enorm
with norm2
everywhere it occurs. If deemed necessary, the original implementation can be preserved as an external subroutine in a "compatibility" folder for older compilers.
I'd also be interested in learning what type of tests can we come up with to prove the "worthiness" of the intrinsic norm2
over the MINPACK-1 algorithm.
Literature
- A Portable Fortran Program to Find the Euclidean Norm of a Vector (1978) | https://doi.org/10.1145/355769.355771
- Efficient Calculations of Faithfully Rounded l2-Norms of n-Vectors (2015) | https://doi.org/10.1145/2699469
- Remark on Algorithm 539: A Modern Fortran Reference Implementation for Carefully Computing the Euclidean Norm (2017) | https://dl.acm.org/doi/10.1145/3134441
- Algorithm 978: Safe Scaling in the Level 1 BLAS (2017) | https://doi.org/10.1145/3061665
- A Rapid Euclidean Norm Calculation Algorithm that Reduces Overflow and Underflow (2021) | https://doi.org/10.1007/978-3-030-86653-2_7
- Accurate calculation of Euclidean Norms using Double-word arithmetic (2022) | https://hal.archives-ouvertes.fr/hal-03482567/