@@ -162,7 +162,7 @@ submodule(stdlib_linalg) stdlib_linalg_norms
162
162
163
163
! Check if this input can be read as an integer
164
164
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
166
166
! Cannot read as an integer
167
167
err = linalg_state_type(this,LINALG_ERROR,'Matrix norm input',order,' is not recognized.')
168
168
endif
@@ -482,10 +482,15 @@ ${loop_variables_end(rank-1," "*12)}$
482
482
allocate(work(m))
483
483
else
484
484
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
489
494
490
495
if (mat_task==MAT_NORM_INF) deallocate(work)
491
496
@@ -507,7 +512,7 @@ ${loop_variables_end(rank-1," "*12)}$
507
512
type(linalg_state_type), intent(out), optional :: err
508
513
509
514
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
511
516
integer(ilp), dimension(${rank}$) :: s,spack,perm,iperm
512
517
integer(ilp), dimension(${rank}$), parameter :: dim_range = [(m,m=1_ilp,${rank}$_ilp)]
513
518
integer(ilp) :: ${loop_variables('j',rank-2,2)}$
@@ -525,6 +530,7 @@ ${loop_variables_end(rank-1," "*12)}$
525
530
endif
526
531
527
532
nullify(apack)
533
+ svd_errors = 0
528
534
529
535
if (dims(1)==dims(2) .or. .not.all(dims>0 .and. dims<=${rank}$)) then
530
536
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)}$
551
557
m = s(dims(1))
552
558
n = s(dims(2))
553
559
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
+
554
567
! Get packed data with norm dimensions as 1:2
555
568
if (contiguous_data) then
556
569
@@ -570,6 +583,8 @@ ${loop_variables_end(rank-1," "*12)}$
570
583
571
584
if (mat_task==MAT_NORM_INF) then
572
585
allocate(work(m))
586
+ elseif (mat_task==MAT_NORM_SVD) then
587
+ allocate(work(min(m,n)))
573
588
else
574
589
work => work1
575
590
endif
@@ -581,12 +596,23 @@ ${loop_variables_end(rank-1," "*12)}$
581
596
582
597
! LAPACK interface
583
598
${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
586
607
${loop_variables_end(rank-2)}$
587
608
588
- if (mat_task==MAT_NORM_INF) deallocate(work)
609
+ if (any( mat_task==[ MAT_NORM_INF,MAT_NORM_SVD]) ) deallocate(work)
589
610
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
590
616
591
617
end function matrix_norm_${rank}$D_to_${rank-2}$D_${ii}$_${ri}$
592
618
0 commit comments