Skip to content

Commit c0da712

Browse files
committed
working implementation
1 parent f39bf52 commit c0da712

File tree

1 file changed

+32
-27
lines changed

1 file changed

+32
-27
lines changed

src/stdlib_linalg_inverse.fypp

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
#:include "common.fypp"
2-
! Compute matrix inverse
2+
#:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
33
module stdlib_linalg_inverse
4+
!! Compute inverse of a square matrix
45
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
99
implicit none(type,external)
1010
private
1111

12+
character(*), parameter :: this = 'inverse'
13+
1214
!> Function interface return the matrix inverse
1315
public :: inv
1416
!> Subroutine interface: invert matrix inplace
@@ -22,49 +24,54 @@ module stdlib_linalg_inverse
2224

2325
! Function interface
2426
interface inv
25-
#:for rk,rt,ri in ALL_KINDS_TYPES
27+
#:for rk,rt,ri in RC_KINDS_TYPES
28+
#:if rk!="xdp"
2629
module procedure stdlib_linalg_inverse_${ri}$
30+
#:endif
2731
#:endfor
2832
end interface inv
2933

3034
! Subroutine interface: in-place factorization
3135
interface invert
32-
#:for rk,rt,ri in ALL_KINDS_TYPES
36+
#:for rk,rt,ri in RC_KINDS_TYPES
37+
#:if rk!="xdp"
3338
module procedure stdlib_linalg_invert_${ri}$
39+
#:endif
3440
#:endfor
3541
end interface invert
3642

3743
! Operator interface
3844
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"
4047
module procedure stdlib_linalg_inverse_${ri}$_operator
48+
#:endif
4149
#:endfor
4250
end interface operator(.inv.)
4351

4452
contains
4553

46-
#:for rk,rt,ri in ALL_KINDS_TYPES
47-
54+
#:for rk,rt,ri in RC_KINDS_TYPES
55+
#:if rk!="xdp"
4856
! Compute the in-place square matrix inverse of a
4957
subroutine stdlib_linalg_invert_${ri}$(a,err)
5058
!> Input matrix a[n,n]
51-
${rt}$, intent(inout) :: a(:,:)
59+
${rt}$, intent(inout) :: a(:,:)
5260
!> [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
5462

5563
!> Local variables
56-
type(linalg_state) :: err0
64+
type(linalg_state_type) :: err0
5765
integer(ilp) :: lda,n,info,nb,lwork
5866
integer(ilp), allocatable :: ipiv(:)
5967
${rt}$, allocatable :: work(:)
60-
character(*), parameter :: this = 'invert'
6168

6269
!> Problem sizes
6370
lda = size(a,1,kind=ilp)
6471
n = size(a,2,kind=ilp)
6572

6673
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,']')
6875
goto 1
6976
end if
7077

@@ -77,9 +84,9 @@ module stdlib_linalg_inverse
7784
! Return codes from getrf and getri are identical
7885
if (info==0) then
7986

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)
8188
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)
8390

8491
allocate(work(lwork))
8592

@@ -92,12 +99,12 @@ module stdlib_linalg_inverse
9299
case (0)
93100
! Success
94101
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,']')
96103
case (1:)
97104
! Matrix is singular
98-
err0 = linalg_state(this,LINALG_ERROR,'singular matrix')
105+
err0 = linalg_state_type(this,LINALG_ERROR,'singular matrix')
99106
case default
100-
err0 = linalg_state(this,LINALG_INTERNAL_ERROR,'catastrophic error')
107+
err0 = linalg_state_type(this,LINALG_INTERNAL_ERROR,'catastrophic error')
101108
end select
102109

103110
! Process output and return
@@ -112,7 +119,7 @@ module stdlib_linalg_inverse
112119
!> Output matrix inverse
113120
${rt}$, allocatable :: inva(:,:)
114121
!> [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
116123

117124
!> Allocate with copy
118125
allocate(inva,source=a)
@@ -129,18 +136,16 @@ module stdlib_linalg_inverse
129136
!> Result matrix
130137
${rt}$, allocatable :: inva(:,:)
131138

132-
type(linalg_state) :: err
139+
type(linalg_state_type) :: err0
133140

134-
inva = stdlib_linalg_inverse_${ri}$(a,err)
141+
inva = stdlib_linalg_inverse_${ri}$(a,err0)
135142

136143
! 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}$
141145

142146
end function stdlib_linalg_inverse_${ri}$_operator
143147

148+
#:endif
144149
#:endfor
145150

146151
end module stdlib_linalg_inverse

0 commit comments

Comments
 (0)