Skip to content

Commit e1d49d8

Browse files
committed
base implementation
1 parent 42aa3e5 commit e1d49d8

File tree

1 file changed

+38
-34
lines changed

1 file changed

+38
-34
lines changed

src/stdlib_linalg_svd.fypp

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#:include "common.fypp"
2+
#:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
23
module stdlib_linalg_svd
4+
!! Singular-Value Decomposition
35
use stdlib_linalg_constants
4-
use stdlib_linalg_blas
5-
use stdlib_linalg_lapack
6-
use stdlib_linalg_state
7-
use iso_fortran_env,only:real32,real64,real128,int8,int16,int32,int64,stderr => error_unit
6+
use stdlib_linalg_lapack, only: gesdd
7+
use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, &
8+
LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR, LINALG_SUCCESS
89
implicit none(type,external)
9-
private
10+
11+
character(*), parameter :: this = 'svd'
1012

1113
!> Singular value decomposition
1214
public :: svd
@@ -17,14 +19,18 @@ module stdlib_linalg_svd
1719
! Scipy: svd(a, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True, lapack_driver='gesdd')
1820

1921
interface svd
20-
#:for rk,rt,ri in ALL_KINDS_TYPES
22+
#:for rk,rt,ri in RC_KINDS_TYPES
23+
#:if rk!="xdp"
2124
module procedure stdlib_linalg_svd_${ri}$
25+
#:endif
2226
#:endfor
2327
end interface svd
2428

2529
interface svdvals
26-
#:for rk,rt,ri in ALL_KINDS_TYPES
30+
#:for rk,rt,ri in RC_KINDS_TYPES
31+
#:if rk!="xdp"
2732
module procedure stdlib_linalg_svdvals_${ri}$
33+
#:endif
2834
#:endfor
2935
end interface svdvals
3036

@@ -40,15 +46,15 @@ module stdlib_linalg_svd
4046
!> Do not return either U or VT (singular values array only)
4147
character, parameter :: GESDD_SINGVAL_ONLY = 'N'
4248

43-
character(*), parameter :: this = 'svd'
49+
4450

4551

4652
contains
4753

4854
!> Process GESDD output flag
49-
elemental subroutine gesdd_info(err,info,m,n)
55+
elemental subroutine handle_gesdd_info(err,info,m,n)
5056
!> Error handler
51-
type(linalg_state), intent(inout) :: err
57+
type(linalg_state_type), intent(inout) :: err
5258
!> GESDD return flag
5359
integer(ilp), intent(in) :: info
5460
!> Input matrix size
@@ -59,32 +65,33 @@ module stdlib_linalg_svd
5965
! Success!
6066
err%state = LINALG_SUCCESS
6167
case (-1)
62-
err = linalg_state(this,LINALG_INTERNAL_ERROR,'Invalid task ID on input to GESDD.')
68+
err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Invalid task ID on input to GESDD.')
6369
case (-5,-3:-2)
64-
err = linalg_state(this,LINALG_VALUE_ERROR,'invalid matrix size: a=[',m,',',n,']')
70+
err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size: a=[',m,',',n,']')
6571
case (-8)
66-
err = linalg_state(this,LINALG_VALUE_ERROR,'invalid matrix U size, with a=[',m,',',n,']')
72+
err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix U size, with a=[',m,',',n,']')
6773
case (-10)
68-
err = linalg_state(this,LINALG_VALUE_ERROR,'invalid matrix V size, with a=[',m,',',n,']')
74+
err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix V size, with a=[',m,',',n,']')
6975
case (-4)
70-
err = linalg_state(this,LINALG_VALUE_ERROR,'A contains invalid/NaN values.')
76+
err = linalg_state_type(this,LINALG_VALUE_ERROR,'A contains invalid/NaN values.')
7177
case (1:)
72-
err = linalg_state(this,LINALG_ERROR,'SVD computation did not converge.')
78+
err = linalg_state_type(this,LINALG_ERROR,'SVD computation did not converge.')
7379
case default
74-
err = linalg_state(this,LINALG_INTERNAL_ERROR,'Unknown error returned by GESDD.')
80+
err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'Unknown error returned by GESDD.')
7581
end select
7682

77-
end subroutine gesdd_info
83+
end subroutine handle_gesdd_info
7884

7985

80-
#:for rk,rt,ri in ALL_KINDS_TYPES
86+
#:for rk,rt,ri in RC_KINDS_TYPES
87+
#:if rk!="xdp"
8188

8289
!> Singular values of matrix A
8390
function stdlib_linalg_svdvals_${ri}$(a,err) result(s)
8491
!> Input matrix A[m,n]
8592
${rt}$, intent(in), target :: a(:,:)
8693
!> [optional] state return flag. On error if not requested, the code will stop
87-
type(linalg_state), optional, intent(out) :: err
94+
type(linalg_state_type), optional, intent(out) :: err
8895
!> Array of singular values
8996
real(${rk}$), allocatable :: s(:)
9097

@@ -123,10 +130,10 @@ module stdlib_linalg_svd
123130
!> they are shape(u)==[m,k] and shape(vh)==[k,n] with k=min(m,n)
124131
logical(lk), optional, intent(in) :: full_matrices
125132
!> [optional] state return flag. On error if not requested, the code will stop
126-
type(linalg_state), optional, intent(out) :: err
133+
type(linalg_state_type), optional, intent(out) :: err
127134

128135
!> Local variables
129-
type(linalg_state) :: err0
136+
type(linalg_state_type) :: err0
130137
integer(ilp) :: m,n,lda,ldu,ldvt,info,k,lwork,liwork,lrwork
131138
integer(ilp), allocatable :: iwork(:)
132139
logical(lk) :: copy_a,full_storage,compute_uv,alloc_u,alloc_vt,can_overwrite_a
@@ -143,12 +150,12 @@ module stdlib_linalg_svd
143150
lda = m
144151

145152
if (.not.k>0) then
146-
err0 = linalg_state(this,LINALG_VALUE_ERROR,'invalid or matrix size: a=[',m,',',n,']')
153+
err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid or matrix size: a=[',m,',',n,']')
147154
goto 1
148155
end if
149156

150157
if (.not.size(s,kind=ilp)>=k) then
151-
err0 = linalg_state(this,LINALG_VALUE_ERROR,'singular value array has insufficient size:',&
158+
err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'singular value array has insufficient size:',&
152159
' s=[',size(s,kind=ilp),'], k=',k)
153160
goto 1
154161
endif
@@ -167,17 +174,13 @@ module stdlib_linalg_svd
167174
! Initialize a matrix temporary
168175
if (copy_a) then
169176
allocate(amat(m,n),source=a)
170-
171-
! Check if we can overwrite A with data that will be lost
172-
can_overwrite_a = merge(.not.present(u),.not.present(vt),m>=n)
173-
174177
else
175178
amat => a
176-
177-
can_overwrite_a = .false.
178-
179179
endif
180-
180+
181+
! Check if we can overwrite A with data that will be lost
182+
can_overwrite_a = copy_a .and. merge(.not.present(u),.not.present(vt),m>=n)
183+
181184
! Full-size matrices
182185
if (present(full_matrices)) then
183186
full_storage = full_matrices
@@ -248,7 +251,7 @@ module stdlib_linalg_svd
248251

249252
call gesdd(task,m,n,amat,lda,s,umat,ldu,vtmat,ldvt,&
250253
work_dummy,lwork,#{if rt.startswith('complex')}#rwork,#{endif}#iwork,info)
251-
call gesdd_info(err0,info,m,n)
254+
call handle_gesdd_info(err0,info,m,n)
252255

253256
! Compute SVD
254257
if (info==0) then
@@ -260,7 +263,7 @@ module stdlib_linalg_svd
260263
!> Compute SVD
261264
call gesdd(task,m,n,amat,lda,s,umat,ldu,vtmat,ldvt,&
262265
work,lwork,#{if rt.startswith('comp')}#rwork,#{endif}#iwork,info)
263-
call gesdd_info(err0,info,m,n)
266+
call handle_gesdd_info(err0,info,m,n)
264267

265268
endif
266269

@@ -271,6 +274,7 @@ module stdlib_linalg_svd
271274
1 call linalg_error_handling(err0,err)
272275

273276
end subroutine stdlib_linalg_svd_${ri}$
277+
#:endif
274278
#:endfor
275279

276280
end module stdlib_linalg_svd

0 commit comments

Comments
 (0)