1
1
#:include "common.fypp"
2
- ! Compute matrix inverse
2
+ #:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
3
3
module stdlib_linalg_inverse
4
+ !! Compute inverse of a square matrix
4
5
use stdlib_linalg_constants
5
- use stdlib_linalg_blas
6
- use stdlib_linalg_lapack
7
- use stdlib_linalg_state
8
- use iso_fortran_env,only:real32,real64,real128,int8,int16,int32,int64,stderr => error_unit
6
+ use stdlib_linalg_lapack, only: getri,getrf,stdlib_ilaenv
7
+ use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, &
8
+ LINALG_INTERNAL_ERROR, LINALG_VALUE_ERROR
9
9
implicit none(type,external)
10
10
private
11
11
12
+ character(*), parameter :: this = 'inverse'
13
+
12
14
!> Function interface return the matrix inverse
13
15
public :: inv
14
16
!> Subroutine interface: invert matrix inplace
@@ -22,49 +24,54 @@ module stdlib_linalg_inverse
22
24
23
25
! Function interface
24
26
interface inv
25
- #:for rk,rt,ri in ALL_KINDS_TYPES
27
+ #:for rk,rt,ri in RC_KINDS_TYPES
28
+ #:if rk!="xdp"
26
29
module procedure stdlib_linalg_inverse_${ri}$
30
+ #:endif
27
31
#:endfor
28
32
end interface inv
29
33
30
34
! Subroutine interface: in-place factorization
31
35
interface invert
32
- #:for rk,rt,ri in ALL_KINDS_TYPES
36
+ #:for rk,rt,ri in RC_KINDS_TYPES
37
+ #:if rk!="xdp"
33
38
module procedure stdlib_linalg_invert_${ri}$
39
+ #:endif
34
40
#:endfor
35
41
end interface invert
36
42
37
43
! Operator interface
38
44
interface operator(.inv.)
39
- #:for rk,rt,ri in ALL_KINDS_TYPES
45
+ #:for rk,rt,ri in RC_KINDS_TYPES
46
+ #:if rk!="xdp"
40
47
module procedure stdlib_linalg_inverse_${ri}$_operator
48
+ #:endif
41
49
#:endfor
42
50
end interface operator(.inv.)
43
51
44
52
contains
45
53
46
- #:for rk,rt,ri in ALL_KINDS_TYPES
47
-
54
+ #:for rk,rt,ri in RC_KINDS_TYPES
55
+ #:if rk!="xdp"
48
56
! Compute the in-place square matrix inverse of a
49
57
subroutine stdlib_linalg_invert_${ri}$(a,err)
50
58
!> Input matrix a[n,n]
51
- ${rt}$, intent(inout) :: a(:,:)
59
+ ${rt}$, intent(inout) :: a(:,:)
52
60
!> [optional] state return flag. On error if not requested, the code will stop
53
- type(linalg_state ), optional, intent(out) :: err
61
+ type(linalg_state_type ), optional, intent(out) :: err
54
62
55
63
!> Local variables
56
- type(linalg_state ) :: err0
64
+ type(linalg_state_type ) :: err0
57
65
integer(ilp) :: lda,n,info,nb,lwork
58
66
integer(ilp), allocatable :: ipiv(:)
59
67
${rt}$, allocatable :: work(:)
60
- character(*), parameter :: this = 'invert'
61
68
62
69
!> Problem sizes
63
70
lda = size(a,1,kind=ilp)
64
71
n = size(a,2,kind=ilp)
65
72
66
73
if (lda<1 .or. n<1 .or. lda/=n) then
67
- err0 = linalg_state (this,LINALG_VALUE_ERROR,'invalid matrix size: a=[',lda,',',n,']')
74
+ err0 = linalg_state_type (this,LINALG_VALUE_ERROR,'invalid matrix size: a=[',lda,',',n,']')
68
75
goto 1
69
76
end if
70
77
@@ -77,9 +84,9 @@ module stdlib_linalg_inverse
77
84
! Return codes from getrf and getri are identical
78
85
if (info==0) then
79
86
80
- ! Get optimal worksize (returned in work(1)) (apply 2% safety parameter )
87
+ ! Get optimal worksize (returned in work(1)) (inflate by a 2% safety margin )
81
88
nb = stdlib_ilaenv(1,'${ri}$getri',' ',n,-1,-1,-1)
82
- lwork = nint (1.02*n*nb,kind=ilp)
89
+ lwork = ceiling (1.02*n*nb,kind=ilp)
83
90
84
91
allocate(work(lwork))
85
92
@@ -92,12 +99,12 @@ module stdlib_linalg_inverse
92
99
case (0)
93
100
! Success
94
101
case (:-1)
95
- err0 = linalg_state (this,LINALG_ERROR,'invalid matrix size a=[',lda,',',n,']')
102
+ err0 = linalg_state_type (this,LINALG_ERROR,'invalid matrix size a=[',lda,',',n,']')
96
103
case (1:)
97
104
! Matrix is singular
98
- err0 = linalg_state (this,LINALG_ERROR,'singular matrix')
105
+ err0 = linalg_state_type (this,LINALG_ERROR,'singular matrix')
99
106
case default
100
- err0 = linalg_state (this,LINALG_INTERNAL_ERROR,'catastrophic error')
107
+ err0 = linalg_state_type (this,LINALG_INTERNAL_ERROR,'catastrophic error')
101
108
end select
102
109
103
110
! Process output and return
@@ -112,7 +119,7 @@ module stdlib_linalg_inverse
112
119
!> Output matrix inverse
113
120
${rt}$, allocatable :: inva(:,:)
114
121
!> [optional] state return flag. On error if not requested, the code will stop
115
- type(linalg_state ), optional, intent(out) :: err
122
+ type(linalg_state_type ), optional, intent(out) :: err
116
123
117
124
!> Allocate with copy
118
125
allocate(inva,source=a)
@@ -129,18 +136,16 @@ module stdlib_linalg_inverse
129
136
!> Result matrix
130
137
${rt}$, allocatable :: inva(:,:)
131
138
132
- type(linalg_state ) :: err
139
+ type(linalg_state_type ) :: err0
133
140
134
- inva = stdlib_linalg_inverse_${ri}$(a,err )
141
+ inva = stdlib_linalg_inverse_${ri}$(a,err0 )
135
142
136
143
! On error, return an empty matrix
137
- if (err%error()) then
138
- if (allocated(inva)) deallocate(inva)
139
- allocate(inva(0,0))
140
- endif
144
+ if (err0%error()) inva = 0.0_${rk}$
141
145
142
146
end function stdlib_linalg_inverse_${ri}$_operator
143
147
148
+ #:endif
144
149
#:endfor
145
150
146
151
end module stdlib_linalg_inverse
0 commit comments