Skip to content

Commit f6d07f8

Browse files
committed
streamline ND->1D norm functions
1 parent 5f6b5e8 commit f6d07f8

File tree

1 file changed

+49
-32
lines changed

1 file changed

+49
-32
lines changed

src/stdlib_linalg_norms.fypp

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
! Vector norms
99
submodule(stdlib_linalg) stdlib_linalg_norms
1010
use stdlib_linalg_constants
11-
use stdlib_linalg_blas, only: nrm2,asum
12-
use stdlib_linalg_lapack, only: lange
11+
use stdlib_linalg_blas
12+
use stdlib_linalg_lapack
1313
use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, &
1414
LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR
1515
use iso_c_binding, only: c_intptr_t,c_char,c_loc
@@ -119,6 +119,47 @@ submodule(stdlib_linalg) stdlib_linalg_norms
119119

120120
end function stride_1d_${ri}$
121121

122+
! Private internal implementation: 1D
123+
pure subroutine internal_norm_1D_${ri}$(sze, a, nrm, norm_request, err)
124+
!> Input matrix length
125+
integer(ilp), intent(in) :: sze
126+
!> Input contiguous 1-d matrix a(*)
127+
${rt}$, intent(in) :: a(sze)
128+
!> Norm of the matrix.
129+
real(${rk}$), intent(out) :: nrm
130+
!> Internal matrix request
131+
integer(ilp), intent(in) :: norm_request
132+
!> State return flag. On error if not requested, the code will stop
133+
type(linalg_state_type), intent(inout) :: err
134+
135+
integer(ilp) :: i
136+
real(${rk}$) :: rorder
137+
intrinsic :: abs, sum, sqrt, maxval, minval, conjg
138+
139+
! Initialize norm to zero
140+
nrm = 0.0_${rk}$
141+
142+
select case(norm_request)
143+
case(NORM_ONE)
144+
nrm = asum(sze,a,incx=1_ilp)
145+
case(NORM_TWO)
146+
nrm = nrm2(sze,a,incx=1_ilp)
147+
case(NORM_INF)
148+
#:if rt.startswith('complex')
149+
! The default BLAS stdlib_i${ri}$amax uses |Re(.)|+|Im(.)|. Do not use it.
150+
i = stdlib_i${ri}$max1(sze,a,incx=1_ilp)
151+
#:else
152+
i = stdlib_i${ri}$amax(sze,a,incx=1_ilp)
153+
#:endif
154+
nrm = abs(a(i))
155+
case(NORM_MINUSINF)
156+
nrm = minval( abs(a) )
157+
case (NORM_POW_FIRST:NORM_POW_LAST)
158+
rorder = 1.0_${rk}$ / norm_request
159+
nrm = sum( abs(a) ** norm_request ) ** rorder
160+
end select
161+
162+
end subroutine internal_norm_1D_${ri}$
122163

123164
#:for it,ii in INPUT_OPTIONS
124165

@@ -155,8 +196,8 @@ submodule(stdlib_linalg) stdlib_linalg_norms
155196
call norm_${rank}$D_${ii}$_${ri}$(a, nrm=nrm, order=order, err=err)
156197

157198
end function stdlib_linalg_norm_${rank}$D_order_err_${ii}$_${ri}$
158-
159-
! Internal implementation
199+
200+
! Internal implementation: ${rank}$-d
160201
pure module subroutine norm_${rank}$D_${ii}$_${ri}$(a, nrm, order, err)
161202
!> Input ${rank}$-d matrix a${ranksuffix(rank)}$
162203
${rt}$, intent(in), target :: a${ranksuffix(rank)}$
@@ -168,7 +209,6 @@ submodule(stdlib_linalg) stdlib_linalg_norms
168209
type(linalg_state_type), intent(out), optional :: err
169210

170211
type(linalg_state_type) :: err_
171-
172212
integer(ilp) :: sze,norm_request
173213
real(${rk}$) :: rorder
174214
intrinsic :: abs, sum, sqrt, maxval, minval, conjg
@@ -190,34 +230,11 @@ submodule(stdlib_linalg) stdlib_linalg_norms
190230
if (err_%error()) then
191231
call linalg_error_handling(err_,err)
192232
return
193-
endif
233+
endif
194234

195-
select case(norm_request)
196-
case(NORM_ONE)
197-
#:if rank==1
198-
nrm = asum(sze,a,incx=1_ilp)
199-
#:else
200-
nrm = sum( abs(a) )
201-
#:endif
202-
case(NORM_TWO)
203-
#:if rank==1
204-
nrm = nrm2(sze,a,incx=1_ilp)
205-
#:elif rt.startswith('complex')
206-
nrm = sqrt( real( sum( a * conjg(a) ), ${rk}$) )
207-
#:else
208-
nrm = norm2(a)
209-
#:endif
210-
case(NORM_INF)
211-
nrm = maxval( abs(a) )
212-
case(NORM_MINUSINF)
213-
nrm = minval( abs(a) )
214-
case (NORM_POW_FIRST:NORM_POW_LAST)
215-
rorder = 1.0_${rk}$ / norm_request
216-
nrm = sum( abs(a) ** norm_request ) ** rorder
217-
case default
218-
err_ = linalg_state_type(this,LINALG_INTERNAL_ERROR,'invalid norm type after checking')
219-
call linalg_error_handling(err_,err)
220-
end select
235+
! Get norm
236+
call internal_norm_1D_${ri}$(sze, a, nrm, norm_request, err_)
237+
call linalg_error_handling(err_,err)
221238

222239
end subroutine norm_${rank}$D_${ii}$_${ri}$
223240

0 commit comments

Comments
 (0)