@@ -10,7 +10,6 @@ module stdlib_linalg_solve
10
10
use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, &
11
11
LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR
12
12
implicit none(type,external)
13
- private
14
13
15
14
!> Solve a linear system
16
15
public :: solve
@@ -24,13 +23,40 @@ module stdlib_linalg_solve
24
23
#:for rk,rt,ri in RC_KINDS_TYPES
25
24
#:if rk!="xdp"
26
25
module procedure stdlib_linalg_${ri}$solve${ndsuf}$
26
+ module procedure stdlib_linalg_${ri}$_pure_solve${ndsuf}$
27
27
#:endif
28
28
#:endfor
29
29
#:endfor
30
30
end interface solve
31
-
31
+
32
+
33
+ character(*), parameter :: this = 'solve'
32
34
33
35
contains
36
+
37
+ elemental subroutine handle_gesv_info(info,lda,n,nrhs,err)
38
+ integer(ilp), intent(in) :: info,lda,n,nrhs
39
+ type(linalg_state_type), intent(out) :: err
40
+
41
+ ! Process output
42
+ select case (info)
43
+ case (0)
44
+ ! Success
45
+ case (-1)
46
+ err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid problem size n=',n)
47
+ case (-2)
48
+ err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid rhs size n=',nrhs)
49
+ case (-4)
50
+ err = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size a=',[lda,n])
51
+ case (-7)
52
+ err = linalg_state_type(this,LINALG_ERROR,'invalid matrix size a=',[lda,n])
53
+ case (1:)
54
+ err = linalg_state_type(this,LINALG_ERROR,'singular matrix')
55
+ case default
56
+ err = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error')
57
+ end select
58
+
59
+ end subroutine handle_gesv_info
34
60
35
61
#:for nd,ndsuf,nde in ALL_RHS
36
62
#:for rk,rt,ri in RC_KINDS_TYPES
@@ -44,7 +70,7 @@ module stdlib_linalg_solve
44
70
!> [optional] Can A data be overwritten and destroyed?
45
71
logical(lk), optional, intent(in) :: overwrite_a
46
72
!> [optional] state return flag. On error if not requested, the code will stop
47
- type(linalg_state_type), optional, intent(out) :: err
73
+ type(linalg_state_type), intent(out) :: err
48
74
!> Result array/matrix x[n] or x[n,nrhs]
49
75
${rt}$, allocatable, target :: x${nd}$
50
76
@@ -53,20 +79,20 @@ module stdlib_linalg_solve
53
79
integer(ilp) :: lda,n,ldb,nrhs,info
54
80
integer(ilp), allocatable :: ipiv(:)
55
81
logical(lk) :: copy_a
56
- ${rt}$, pointer :: xmat(:,:),amat(:,:)
57
- character(*), parameter :: this = 'solve'
82
+ ${rt}$, pointer :: xmat(:,:),amat(:,:)
58
83
59
84
!> Problem sizes
60
85
lda = size(a,1,kind=ilp)
61
86
n = size(a,2,kind=ilp)
62
87
ldb = size(b,1,kind=ilp)
63
88
nrhs = size(b ,kind=ilp)/ldb
64
89
65
- if (lda<1 .or. n<1 .or. ldb<1 .or. lda/=n .or. ldb/=n) then
66
- err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid sizes: a=[', lda,',',n,'],', &
67
- 'b=[', ldb,',', nrhs,']' )
90
+ if (any([ lda,n, ldb]<1) .or. any([ lda, ldb] /=n) ) then
91
+ err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid sizes: a=',[ lda,n], &
92
+ ', b=',[ ldb,nrhs] )
68
93
allocate(x${nde}$)
69
- goto 1
94
+ call linalg_error_handling(err0,err)
95
+ return
70
96
end if
71
97
72
98
! Can A be overwritten? By default, do not overwrite
@@ -94,30 +120,68 @@ module stdlib_linalg_solve
94
120
call gesv(n,nrhs,amat,lda,ipiv,xmat,ldb,info)
95
121
96
122
! Process output
97
- select case (info)
98
- case (0)
99
- ! Success
100
- case (-1)
101
- err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid problem size n=',n)
102
- case (-2)
103
- err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid rhs size n=',nrhs)
104
- case (-4)
105
- err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid matrix size a=[',lda,',',n,']')
106
- case (-7)
107
- err0 = linalg_state_type(this,LINALG_ERROR,'invalid matrix size a=[',lda,',',n,']')
108
- case (1:)
109
- err0 = linalg_state_type(this,LINALG_ERROR,'singular matrix')
110
- case default
111
- err0 = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error')
112
- end select
123
+ call handle_gesv_info(info,lda,n,nrhs,err0)
113
124
114
- if (.not. copy_a) deallocate(amat)
125
+ if (copy_a) deallocate(amat)
115
126
116
127
! Process output and return
117
- 1 call linalg_error_handling(err0,err)
128
+ call linalg_error_handling(err0,err)
118
129
119
130
end function stdlib_linalg_${ri}$solve${ndsuf}$
120
131
132
+ ! Compute the solution to a real system of linear equations A * X = B (pure interface)
133
+ pure function stdlib_linalg_${ri}$_pure_solve${ndsuf}$(a,b) result(x)
134
+ !> Input matrix a[n,n]
135
+ ${rt}$, intent(in), target :: a(:,:)
136
+ !> Right hand side vector or array, b[n] or b[n,nrhs]
137
+ ${rt}$, intent(in) :: b${nd}$
138
+ !> Result array/matrix x[n] or x[n,nrhs]
139
+ ${rt}$, allocatable, target :: x${nd}$
140
+
141
+ !> Local variables
142
+ type(linalg_state_type) :: err0
143
+ integer(ilp) :: lda,n,ldb,nrhs,info
144
+ integer(ilp), allocatable :: ipiv(:)
145
+ ${rt}$, pointer :: xmat(:,:)
146
+ ${rt}$, allocatable :: amat(:,:)
147
+ character(*), parameter :: this = 'solve'
148
+
149
+ !> Problem sizes
150
+ lda = size(a,1,kind=ilp)
151
+ n = size(a,2,kind=ilp)
152
+ ldb = size(b,1,kind=ilp)
153
+ nrhs = size(b ,kind=ilp)/ldb
154
+
155
+ if (any([lda,n,ldb]<1) .or. any([lda,ldb]/=n)) then
156
+ err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'invalid sizes: a=',[lda,n], &
157
+ ', b=',[ldb,nrhs])
158
+ allocate(x${nde}$)
159
+ call linalg_error_handling(err0)
160
+ return
161
+ end if
162
+
163
+ ! Pivot indices
164
+ allocate(ipiv(n))
165
+
166
+ ! Initialize a matrix temporary
167
+ allocate(amat,source=a)
168
+
169
+ ! Initialize solution with the rhs
170
+ allocate(x,source=b)
171
+ xmat(1:n,1:nrhs) => x
172
+
173
+ ! Solve system
174
+ call gesv(n,nrhs,amat,lda,ipiv,xmat,ldb,info)
175
+
176
+ ! Process output
177
+ call handle_gesv_info(info,lda,n,nrhs,err0)
178
+
179
+ deallocate(amat)
180
+
181
+ ! Process output and return
182
+ call linalg_error_handling(err0)
183
+
184
+ end function stdlib_linalg_${ri}$_pure_solve${ndsuf}$
121
185
#:endif
122
186
#:endfor
123
187
#:endfor
0 commit comments