1
1
#:include "common.fypp"
2
+ #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
2
3
module stdlib_linalg_svd
4
+ !! Singular-Value Decomposition
3
5
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
8
9
implicit none(type,external)
9
- private
10
+
11
+ character(*), parameter :: this = 'svd'
10
12
11
13
!> Singular value decomposition
12
14
public :: svd
@@ -17,14 +19,18 @@ module stdlib_linalg_svd
17
19
! Scipy: svd(a, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True, lapack_driver='gesdd')
18
20
19
21
interface svd
20
- #:for rk,rt,ri in ALL_KINDS_TYPES
22
+ #:for rk,rt,ri in RC_KINDS_TYPES
23
+ #:if rk!="xdp"
21
24
module procedure stdlib_linalg_svd_${ri}$
25
+ #:endif
22
26
#:endfor
23
27
end interface svd
24
28
25
29
interface svdvals
26
- #:for rk,rt,ri in ALL_KINDS_TYPES
30
+ #:for rk,rt,ri in RC_KINDS_TYPES
31
+ #:if rk!="xdp"
27
32
module procedure stdlib_linalg_svdvals_${ri}$
33
+ #:endif
28
34
#:endfor
29
35
end interface svdvals
30
36
@@ -40,15 +46,15 @@ module stdlib_linalg_svd
40
46
!> Do not return either U or VT (singular values array only)
41
47
character, parameter :: GESDD_SINGVAL_ONLY = 'N'
42
48
43
- character(*), parameter :: this = 'svd'
49
+
44
50
45
51
46
52
contains
47
53
48
54
!> Process GESDD output flag
49
- elemental subroutine gesdd_info (err,info,m,n)
55
+ elemental subroutine handle_gesdd_info (err,info,m,n)
50
56
!> Error handler
51
- type(linalg_state ), intent(inout) :: err
57
+ type(linalg_state_type ), intent(inout) :: err
52
58
!> GESDD return flag
53
59
integer(ilp), intent(in) :: info
54
60
!> Input matrix size
@@ -59,32 +65,33 @@ module stdlib_linalg_svd
59
65
! Success!
60
66
err%state = LINALG_SUCCESS
61
67
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.')
63
69
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,']')
65
71
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,']')
67
73
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,']')
69
75
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.')
71
77
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.')
73
79
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.')
75
81
end select
76
82
77
- end subroutine gesdd_info
83
+ end subroutine handle_gesdd_info
78
84
79
85
80
- #:for rk,rt,ri in ALL_KINDS_TYPES
86
+ #:for rk,rt,ri in RC_KINDS_TYPES
87
+ #:if rk!="xdp"
81
88
82
89
!> Singular values of matrix A
83
90
function stdlib_linalg_svdvals_${ri}$(a,err) result(s)
84
91
!> Input matrix A[m,n]
85
92
${rt}$, intent(in), target :: a(:,:)
86
93
!> [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
88
95
!> Array of singular values
89
96
real(${rk}$), allocatable :: s(:)
90
97
@@ -123,10 +130,10 @@ module stdlib_linalg_svd
123
130
!> they are shape(u)==[m,k] and shape(vh)==[k,n] with k=min(m,n)
124
131
logical(lk), optional, intent(in) :: full_matrices
125
132
!> [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
127
134
128
135
!> Local variables
129
- type(linalg_state ) :: err0
136
+ type(linalg_state_type ) :: err0
130
137
integer(ilp) :: m,n,lda,ldu,ldvt,info,k,lwork,liwork,lrwork
131
138
integer(ilp), allocatable :: iwork(:)
132
139
logical(lk) :: copy_a,full_storage,compute_uv,alloc_u,alloc_vt,can_overwrite_a
@@ -143,12 +150,12 @@ module stdlib_linalg_svd
143
150
lda = m
144
151
145
152
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,']')
147
154
goto 1
148
155
end if
149
156
150
157
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:',&
152
159
' s=[',size(s,kind=ilp),'], k=',k)
153
160
goto 1
154
161
endif
@@ -167,17 +174,13 @@ module stdlib_linalg_svd
167
174
! Initialize a matrix temporary
168
175
if (copy_a) then
169
176
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
-
174
177
else
175
178
amat => a
176
-
177
- can_overwrite_a = .false.
178
-
179
179
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
+
181
184
! Full-size matrices
182
185
if (present(full_matrices)) then
183
186
full_storage = full_matrices
@@ -248,7 +251,7 @@ module stdlib_linalg_svd
248
251
249
252
call gesdd(task,m,n,amat,lda,s,umat,ldu,vtmat,ldvt,&
250
253
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)
252
255
253
256
! Compute SVD
254
257
if (info==0) then
@@ -260,7 +263,7 @@ module stdlib_linalg_svd
260
263
!> Compute SVD
261
264
call gesdd(task,m,n,amat,lda,s,umat,ldu,vtmat,ldvt,&
262
265
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)
264
267
265
268
endif
266
269
@@ -271,6 +274,7 @@ module stdlib_linalg_svd
271
274
1 call linalg_error_handling(err0,err)
272
275
273
276
end subroutine stdlib_linalg_svd_${ri}$
277
+ #:endif
274
278
#:endfor
275
279
276
280
end module stdlib_linalg_svd
0 commit comments