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