@@ -162,7 +162,7 @@ submodule(stdlib_linalg) stdlib_linalg_norms
162162
163163 ! Check if this input can be read as an integer
164164 read(order,*,iostat=read_err) int_order
165- if (read_err/=0 .or. all(int_order/=[1,2]) then
165+ if (read_err/=0 .or. all(int_order/=[1,2])) then
166166 ! Cannot read as an integer
167167 err = linalg_state_type(this,LINALG_ERROR,'Matrix norm input',order,' is not recognized.')
168168 endif
@@ -482,10 +482,15 @@ ${loop_variables_end(rank-1," "*12)}$
482482 allocate(work(m))
483483 else
484484 work => work1
485- endif
486-
487- ! LAPACK interface
488- nrm = lange(mat_task,m,n,a,m,work)
485+ end if
486+
487+ if (mat_task==MAT_NORM_SVD) then
488+ nrm = maxval(svdvals(a,err_),1)
489+ call linalg_error_handling(err_,err)
490+ else
491+ ! LAPACK interface
492+ nrm = lange(mat_task,m,n,a,m,work)
493+ end if
489494
490495 if (mat_task==MAT_NORM_INF) deallocate(work)
491496
@@ -507,7 +512,7 @@ ${loop_variables_end(rank-1," "*12)}$
507512 type(linalg_state_type), intent(out), optional :: err
508513
509514 type(linalg_state_type) :: err_
510- integer(ilp) :: j,m,n,lda,dims(2),norm_request
515+ integer(ilp) :: j,m,n,lda,dims(2),norm_request,svd_errors
511516 integer(ilp), dimension(${rank}$) :: s,spack,perm,iperm
512517 integer(ilp), dimension(${rank}$), parameter :: dim_range = [(m,m=1_ilp,${rank}$_ilp)]
513518 integer(ilp) :: ${loop_variables('j',rank-2,2)}$
@@ -525,6 +530,7 @@ ${loop_variables_end(rank-1," "*12)}$
525530 endif
526531
527532 nullify(apack)
533+ svd_errors = 0
528534
529535 if (dims(1)==dims(2) .or. .not.all(dims>0 .and. dims<=${rank}$)) then
530536 err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'Rank-',${rank}$,' matrix norm has invalid dim=',dims)
@@ -551,6 +557,13 @@ ${loop_variables_end(rank-1," "*12)}$
551557 m = s(dims(1))
552558 n = s(dims(2))
553559
560+ if (m<=0 .or. n<=0) then
561+ err_ = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix shape: a=',[m,n])
562+ allocate(nrm${emptyranksuffix(rank-2)}$)
563+ call linalg_error_handling(err_,err)
564+ return
565+ end if
566+
554567 ! Get packed data with norm dimensions as 1:2
555568 if (contiguous_data) then
556569
@@ -570,6 +583,8 @@ ${loop_variables_end(rank-1," "*12)}$
570583
571584 if (mat_task==MAT_NORM_INF) then
572585 allocate(work(m))
586+ elseif (mat_task==MAT_NORM_SVD) then
587+ allocate(work(min(m,n)))
573588 else
574589 work => work1
575590 endif
@@ -581,12 +596,23 @@ ${loop_variables_end(rank-1," "*12)}$
581596
582597 ! LAPACK interface
583598${loop_variables_start('j', 'apack', rank-2, 2)}$
584- nrm(${loop_variables('j',rank-2,2)}$) = &
585- lange(mat_task,m,n,apack(:,:,${loop_variables('j',rank-2,2)}$),lda,work)
599+ if (mat_task==MAT_NORM_SVD) then
600+ work(:) = svdvals(apack(:,:,${loop_variables('j',rank-2,2)}$),err_)
601+ nrm(${loop_variables('j',rank-2,2)}$) = maxval(work,1)
602+ if (err_%error()) svd_errors = svd_errors+1
603+ else
604+ nrm(${loop_variables('j',rank-2,2)}$) = &
605+ lange(mat_task,m,n,apack(:,:,${loop_variables('j',rank-2,2)}$),lda,work)
606+ end if
586607${loop_variables_end(rank-2)}$
587608
588- if (mat_task==MAT_NORM_INF) deallocate(work)
609+ if (any( mat_task==[ MAT_NORM_INF,MAT_NORM_SVD]) ) deallocate(work)
589610 if (.not.contiguous_data) deallocate(apack)
611+
612+ if (svd_errors>0) then
613+ err_ = linalg_state_type(this,LINALG_VALUE_ERROR,svd_errors,'failed SVDs')
614+ call linalg_error_handling(err_,err)
615+ endif
590616
591617 end function matrix_norm_${rank}$D_to_${rank-2}$D_${ii}$_${ri}$
592618
0 commit comments