Commit 68642e5d21b0cb88b82aa6c7a681e3b448197363
1 parent
204ded3d3d
Exists in
geevx_2020
Using [SDCZ]GEEVX instead of [SDCZ]GEEV to avoid use of
[SDCZ]GEBAL which cause NaN in some circumstances
Showing 1 changed file with 49 additions and 9 deletions Inline Diff
fvn_linear/fvn_linear.f90
module fvn_linear | 1 | 1 | module fvn_linear | |
use fvn_common | 2 | 2 | use fvn_common | |
implicit none | 3 | 3 | implicit none | |
4 | 4 | |||
5 | 5 | |||
! | 6 | 6 | ! | |
! Interfaces for matrix operators | 7 | 7 | ! Interfaces for matrix operators | |
8 | 8 | |||
! .x. matrix multiplication | 9 | 9 | ! .x. matrix multiplication | |
interface operator(.x.) | 10 | 10 | interface operator(.x.) | |
module procedure fvn_op_s_matmul,fvn_op_d_matmul,fvn_op_c_matmul,fvn_op_z_matmul | 11 | 11 | module procedure fvn_op_s_matmul,fvn_op_d_matmul,fvn_op_c_matmul,fvn_op_z_matmul | |
end interface | 12 | 12 | end interface | |
13 | 13 | |||
! .t. matrix transposition | 14 | 14 | ! .t. matrix transposition | |
interface operator(.t.) | 15 | 15 | interface operator(.t.) | |
module procedure fvn_op_s_transpose,fvn_op_d_transpose,fvn_op_c_transpose,fvn_op_z_transpose | 16 | 16 | module procedure fvn_op_s_transpose,fvn_op_d_transpose,fvn_op_c_transpose,fvn_op_z_transpose | |
end interface | 17 | 17 | end interface | |
18 | 18 | |||
! .tx. transpose first operand and multiply | 19 | 19 | ! .tx. transpose first operand and multiply | |
interface operator(.tx.) | 20 | 20 | interface operator(.tx.) | |
module procedure fvn_op_s_tx,fvn_op_d_tx,fvn_op_c_tx,fvn_op_z_tx | 21 | 21 | module procedure fvn_op_s_tx,fvn_op_d_tx,fvn_op_c_tx,fvn_op_z_tx | |
end interface | 22 | 22 | end interface | |
23 | 23 | |||
! .xt. transpose second operand and multiply | 24 | 24 | ! .xt. transpose second operand and multiply | |
interface operator(.xt.) | 25 | 25 | interface operator(.xt.) | |
module procedure fvn_op_s_xt,fvn_op_d_xt,fvn_op_c_xt,fvn_op_z_xt | 26 | 26 | module procedure fvn_op_s_xt,fvn_op_d_xt,fvn_op_c_xt,fvn_op_z_xt | |
end interface | 27 | 27 | end interface | |
28 | 28 | |||
! .i. inverse matrix | 29 | 29 | ! .i. inverse matrix | |
interface operator(.i.) | 30 | 30 | interface operator(.i.) | |
module procedure fvn_op_s_matinv,fvn_op_d_matinv,fvn_op_c_matinv,fvn_op_z_matinv | 31 | 31 | module procedure fvn_op_s_matinv,fvn_op_d_matinv,fvn_op_c_matinv,fvn_op_z_matinv | |
end interface | 32 | 32 | end interface | |
33 | 33 | |||
! .ix. inverse first operand and multiply | 34 | 34 | ! .ix. inverse first operand and multiply | |
interface operator(.ix.) | 35 | 35 | interface operator(.ix.) | |
module procedure fvn_op_s_ix,fvn_op_d_ix,fvn_op_c_ix,fvn_op_z_ix | 36 | 36 | module procedure fvn_op_s_ix,fvn_op_d_ix,fvn_op_c_ix,fvn_op_z_ix | |
end interface | 37 | 37 | end interface | |
38 | 38 | |||
! .xi. inverse second operand and multiply | 39 | 39 | ! .xi. inverse second operand and multiply | |
interface operator(.xi.) | 40 | 40 | interface operator(.xi.) | |
module procedure fvn_op_s_xi,fvn_op_d_xi,fvn_op_c_xi,fvn_op_z_xi | 41 | 41 | module procedure fvn_op_s_xi,fvn_op_d_xi,fvn_op_c_xi,fvn_op_z_xi | |
end interface | 42 | 42 | end interface | |
43 | 43 | |||
! .h. transpose conjugate (adjoint) | 44 | 44 | ! .h. transpose conjugate (adjoint) | |
interface operator(.h.) | 45 | 45 | interface operator(.h.) | |
module procedure fvn_op_s_transpose,fvn_op_d_transpose,fvn_op_c_conj_transpose,fvn_op_z_conj_transpose | 46 | 46 | module procedure fvn_op_s_transpose,fvn_op_d_transpose,fvn_op_c_conj_transpose,fvn_op_z_conj_transpose | |
end interface | 47 | 47 | end interface | |
48 | 48 | |||
! .hx. transpose conjugate first operand and multiply | 49 | 49 | ! .hx. transpose conjugate first operand and multiply | |
interface operator(.hx.) | 50 | 50 | interface operator(.hx.) | |
module procedure fvn_op_s_tx,fvn_op_d_tx,fvn_op_c_hx,fvn_op_z_hx | 51 | 51 | module procedure fvn_op_s_tx,fvn_op_d_tx,fvn_op_c_hx,fvn_op_z_hx | |
end interface | 52 | 52 | end interface | |
53 | 53 | |||
! .xh. transpose conjugate second operand and multiply | 54 | 54 | ! .xh. transpose conjugate second operand and multiply | |
interface operator(.xh.) | 55 | 55 | interface operator(.xh.) | |
module procedure fvn_op_s_xt,fvn_op_d_xt,fvn_op_c_xh,fvn_op_z_xh | 56 | 56 | module procedure fvn_op_s_xt,fvn_op_d_xt,fvn_op_c_xh,fvn_op_z_xh | |
end interface | 57 | 57 | end interface | |
58 | 58 | |||
59 | 59 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 60 | 60 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 61 | 61 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! Generic interface Definition | 62 | 62 | ! Generic interface Definition | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 63 | 63 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 64 | 64 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
65 | 65 | |||
! Matrix inversion | 66 | 66 | ! Matrix inversion | |
interface fvn_matinv | 67 | 67 | interface fvn_matinv | |
module procedure fvn_s_matinv,fvn_d_matinv,fvn_c_matinv,fvn_z_matinv | 68 | 68 | module procedure fvn_s_matinv,fvn_d_matinv,fvn_c_matinv,fvn_z_matinv | |
end interface fvn_matinv | 69 | 69 | end interface fvn_matinv | |
70 | 70 | |||
! Determinant | 71 | 71 | ! Determinant | |
interface fvn_det | 72 | 72 | interface fvn_det | |
module procedure fvn_s_det,fvn_d_det,fvn_c_det,fvn_z_det | 73 | 73 | module procedure fvn_s_det,fvn_d_det,fvn_c_det,fvn_z_det | |
end interface fvn_det | 74 | 74 | end interface fvn_det | |
75 | 75 | |||
! Condition | 76 | 76 | ! Condition | |
interface fvn_matcon | 77 | 77 | interface fvn_matcon | |
module procedure fvn_s_matcon,fvn_d_matcon,fvn_c_matcon,fvn_z_matcon | 78 | 78 | module procedure fvn_s_matcon,fvn_d_matcon,fvn_c_matcon,fvn_z_matcon | |
end interface fvn_matcon | 79 | 79 | end interface fvn_matcon | |
80 | 80 | |||
! Eigen | 81 | 81 | ! Eigen | |
interface fvn_matev | 82 | 82 | interface fvn_matev | |
module procedure fvn_s_matev,fvn_d_matev,fvn_c_matev,fvn_z_matev | 83 | 83 | module procedure fvn_s_matev,fvn_d_matev,fvn_c_matev,fvn_z_matev | |
end interface fvn_matev | 84 | 84 | end interface fvn_matev | |
85 | 85 | |||
! Least square polynomial | 86 | 86 | ! Least square polynomial | |
interface fvn_lspoly | 87 | 87 | interface fvn_lspoly | |
module procedure fvn_s_lspoly,fvn_d_lspoly | 88 | 88 | module procedure fvn_s_lspoly,fvn_d_lspoly | |
end interface fvn_lspoly | 89 | 89 | end interface fvn_lspoly | |
90 | 90 | |||
91 | 91 | |||
contains | 92 | 92 | contains | |
93 | 93 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 94 | 94 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 95 | 95 | ! | |
! Linear operators | 96 | 96 | ! Linear operators | |
! | 97 | 97 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 98 | 98 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
99 | 99 | |||
! | 100 | 100 | ! | |
! .x. | 101 | 101 | ! .x. | |
! | 102 | 102 | ! | |
function fvn_op_s_matmul(a,b) | 103 | 103 | function fvn_op_s_matmul(a,b) | |
implicit none | 104 | 104 | implicit none | |
real(kind=sp_kind), dimension(:,:),intent(in) :: a,b | 105 | 105 | real(kind=sp_kind), dimension(:,:),intent(in) :: a,b | |
real(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_s_matmul | 106 | 106 | real(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_s_matmul | |
fvn_op_s_matmul=matmul(a,b) | 107 | 107 | fvn_op_s_matmul=matmul(a,b) | |
end function | 108 | 108 | end function | |
function fvn_op_d_matmul(a,b) | 109 | 109 | function fvn_op_d_matmul(a,b) | |
implicit none | 110 | 110 | implicit none | |
real(kind=dp_kind), dimension(:,:),intent(in) :: a,b | 111 | 111 | real(kind=dp_kind), dimension(:,:),intent(in) :: a,b | |
real(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_d_matmul | 112 | 112 | real(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_d_matmul | |
fvn_op_d_matmul=matmul(a,b) | 113 | 113 | fvn_op_d_matmul=matmul(a,b) | |
end function | 114 | 114 | end function | |
function fvn_op_c_matmul(a,b) | 115 | 115 | function fvn_op_c_matmul(a,b) | |
implicit none | 116 | 116 | implicit none | |
complex(kind=sp_kind), dimension(:,:),intent(in) :: a,b | 117 | 117 | complex(kind=sp_kind), dimension(:,:),intent(in) :: a,b | |
complex(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_c_matmul | 118 | 118 | complex(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_c_matmul | |
fvn_op_c_matmul=matmul(a,b) | 119 | 119 | fvn_op_c_matmul=matmul(a,b) | |
end function | 120 | 120 | end function | |
function fvn_op_z_matmul(a,b) | 121 | 121 | function fvn_op_z_matmul(a,b) | |
implicit none | 122 | 122 | implicit none | |
complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 123 | 123 | complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_z_matmul | 124 | 124 | complex(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_z_matmul | |
fvn_op_z_matmul=matmul(a,b) | 125 | 125 | fvn_op_z_matmul=matmul(a,b) | |
end function | 126 | 126 | end function | |
127 | 127 | |||
! | 128 | 128 | ! | |
! .tx. | 129 | 129 | ! .tx. | |
! | 130 | 130 | ! | |
function fvn_op_s_tx(a,b) | 131 | 131 | function fvn_op_s_tx(a,b) | |
implicit none | 132 | 132 | implicit none | |
real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 133 | 133 | real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=sp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_s_tx | 134 | 134 | real(kind=sp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_s_tx | |
fvn_op_s_tx=matmul(transpose(a),b) | 135 | 135 | fvn_op_s_tx=matmul(transpose(a),b) | |
end function | 136 | 136 | end function | |
function fvn_op_d_tx(a,b) | 137 | 137 | function fvn_op_d_tx(a,b) | |
implicit none | 138 | 138 | implicit none | |
real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 139 | 139 | real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=dp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_d_tx | 140 | 140 | real(kind=dp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_d_tx | |
fvn_op_d_tx=matmul(transpose(a),b) | 141 | 141 | fvn_op_d_tx=matmul(transpose(a),b) | |
end function | 142 | 142 | end function | |
function fvn_op_c_tx(a,b) | 143 | 143 | function fvn_op_c_tx(a,b) | |
implicit none | 144 | 144 | implicit none | |
complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 145 | 145 | complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=sp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_c_tx | 146 | 146 | complex(kind=sp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_c_tx | |
fvn_op_c_tx=matmul(transpose(a),b) | 147 | 147 | fvn_op_c_tx=matmul(transpose(a),b) | |
end function | 148 | 148 | end function | |
function fvn_op_z_tx(a,b) | 149 | 149 | function fvn_op_z_tx(a,b) | |
implicit none | 150 | 150 | implicit none | |
complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 151 | 151 | complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=dp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_z_tx | 152 | 152 | complex(kind=dp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_z_tx | |
fvn_op_z_tx=matmul(transpose(a),b) | 153 | 153 | fvn_op_z_tx=matmul(transpose(a),b) | |
end function | 154 | 154 | end function | |
155 | 155 | |||
156 | 156 | |||
! | 157 | 157 | ! | |
! .xt. | 158 | 158 | ! .xt. | |
! | 159 | 159 | ! | |
function fvn_op_s_xt(a,b) | 160 | 160 | function fvn_op_s_xt(a,b) | |
implicit none | 161 | 161 | implicit none | |
real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 162 | 162 | real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=sp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_s_xt | 163 | 163 | real(kind=sp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_s_xt | |
fvn_op_s_xt=matmul(a,transpose(b)) | 164 | 164 | fvn_op_s_xt=matmul(a,transpose(b)) | |
end function | 165 | 165 | end function | |
function fvn_op_d_xt(a,b) | 166 | 166 | function fvn_op_d_xt(a,b) | |
implicit none | 167 | 167 | implicit none | |
real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 168 | 168 | real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=dp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_d_xt | 169 | 169 | real(kind=dp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_d_xt | |
fvn_op_d_xt=matmul(a,transpose(b)) | 170 | 170 | fvn_op_d_xt=matmul(a,transpose(b)) | |
end function | 171 | 171 | end function | |
function fvn_op_c_xt(a,b) | 172 | 172 | function fvn_op_c_xt(a,b) | |
implicit none | 173 | 173 | implicit none | |
complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 174 | 174 | complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=sp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_c_xt | 175 | 175 | complex(kind=sp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_c_xt | |
fvn_op_c_xt=matmul(a,transpose(b)) | 176 | 176 | fvn_op_c_xt=matmul(a,transpose(b)) | |
end function | 177 | 177 | end function | |
function fvn_op_z_xt(a,b) | 178 | 178 | function fvn_op_z_xt(a,b) | |
implicit none | 179 | 179 | implicit none | |
complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 180 | 180 | complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=dp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_z_xt | 181 | 181 | complex(kind=dp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_z_xt | |
fvn_op_z_xt=matmul(a,transpose(b)) | 182 | 182 | fvn_op_z_xt=matmul(a,transpose(b)) | |
end function | 183 | 183 | end function | |
184 | 184 | |||
! | 185 | 185 | ! | |
! .t. | 186 | 186 | ! .t. | |
! | 187 | 187 | ! | |
function fvn_op_s_transpose(a) | 188 | 188 | function fvn_op_s_transpose(a) | |
implicit none | 189 | 189 | implicit none | |
real(kind=sp_kind),dimension(:,:),intent(in) :: a | 190 | 190 | real(kind=sp_kind),dimension(:,:),intent(in) :: a | |
real(kind=sp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_s_transpose | 191 | 191 | real(kind=sp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_s_transpose | |
fvn_op_s_transpose=transpose(a) | 192 | 192 | fvn_op_s_transpose=transpose(a) | |
end function | 193 | 193 | end function | |
function fvn_op_d_transpose(a) | 194 | 194 | function fvn_op_d_transpose(a) | |
implicit none | 195 | 195 | implicit none | |
real(kind=dp_kind),dimension(:,:),intent(in) :: a | 196 | 196 | real(kind=dp_kind),dimension(:,:),intent(in) :: a | |
real(kind=dp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_d_transpose | 197 | 197 | real(kind=dp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_d_transpose | |
fvn_op_d_transpose=transpose(a) | 198 | 198 | fvn_op_d_transpose=transpose(a) | |
end function | 199 | 199 | end function | |
function fvn_op_c_transpose(a) | 200 | 200 | function fvn_op_c_transpose(a) | |
implicit none | 201 | 201 | implicit none | |
complex(kind=sp_kind),dimension(:,:),intent(in) :: a | 202 | 202 | complex(kind=sp_kind),dimension(:,:),intent(in) :: a | |
complex(kind=sp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_c_transpose | 203 | 203 | complex(kind=sp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_c_transpose | |
fvn_op_c_transpose=transpose(a) | 204 | 204 | fvn_op_c_transpose=transpose(a) | |
end function | 205 | 205 | end function | |
function fvn_op_z_transpose(a) | 206 | 206 | function fvn_op_z_transpose(a) | |
implicit none | 207 | 207 | implicit none | |
complex(kind=dp_kind),dimension(:,:),intent(in) :: a | 208 | 208 | complex(kind=dp_kind),dimension(:,:),intent(in) :: a | |
complex(kind=dp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_z_transpose | 209 | 209 | complex(kind=dp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_z_transpose | |
fvn_op_z_transpose=transpose(a) | 210 | 210 | fvn_op_z_transpose=transpose(a) | |
end function | 211 | 211 | end function | |
212 | 212 | |||
! | 213 | 213 | ! | |
! .i. | 214 | 214 | ! .i. | |
! | 215 | 215 | ! | |
! It seems that there's a problem with automatic arrays with gfortran | 216 | 216 | ! It seems that there's a problem with automatic arrays with gfortran | |
! in some circumstances. To allow compilation with gfortran we use here a temporary array | 217 | 217 | ! in some circumstances. To allow compilation with gfortran we use here a temporary array | |
! for the call. Without that there's a warning at compile time and a segmentation fault | 218 | 218 | ! for the call. Without that there's a warning at compile time and a segmentation fault | |
! during execution. This is odd as we double memory use. | 219 | 219 | ! during execution. This is odd as we double memory use. | |
function fvn_op_s_matinv(a) | 220 | 220 | function fvn_op_s_matinv(a) | |
implicit none | 221 | 221 | implicit none | |
real(kind=sp_kind),dimension(:,:),intent(in) :: a | 222 | 222 | real(kind=sp_kind),dimension(:,:),intent(in) :: a | |
real(kind=sp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_s_matinv,tmp_array | 223 | 223 | real(kind=sp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_s_matinv,tmp_array | |
call fvn_s_matinv(size(a,1),a,tmp_array,fvn_status) | 224 | 224 | call fvn_s_matinv(size(a,1),a,tmp_array,fvn_status) | |
fvn_op_s_matinv=tmp_array | 225 | 225 | fvn_op_s_matinv=tmp_array | |
end function | 226 | 226 | end function | |
function fvn_op_d_matinv(a) | 227 | 227 | function fvn_op_d_matinv(a) | |
implicit none | 228 | 228 | implicit none | |
real(kind=dp_kind),dimension(:,:),intent(in) :: a | 229 | 229 | real(kind=dp_kind),dimension(:,:),intent(in) :: a | |
real(kind=dp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_d_matinv,tmp_array | 230 | 230 | real(kind=dp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_d_matinv,tmp_array | |
call fvn_d_matinv(size(a,1),a,tmp_array,fvn_status) | 231 | 231 | call fvn_d_matinv(size(a,1),a,tmp_array,fvn_status) | |
fvn_op_d_matinv=tmp_array | 232 | 232 | fvn_op_d_matinv=tmp_array | |
end function | 233 | 233 | end function | |
function fvn_op_c_matinv(a) | 234 | 234 | function fvn_op_c_matinv(a) | |
implicit none | 235 | 235 | implicit none | |
complex(kind=sp_kind),dimension(:,:),intent(in) :: a | 236 | 236 | complex(kind=sp_kind),dimension(:,:),intent(in) :: a | |
complex(kind=sp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_c_matinv,tmp_array | 237 | 237 | complex(kind=sp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_c_matinv,tmp_array | |
call fvn_c_matinv(size(a,1),a,tmp_array,fvn_status) | 238 | 238 | call fvn_c_matinv(size(a,1),a,tmp_array,fvn_status) | |
fvn_op_c_matinv=tmp_array | 239 | 239 | fvn_op_c_matinv=tmp_array | |
end function | 240 | 240 | end function | |
function fvn_op_z_matinv(a) | 241 | 241 | function fvn_op_z_matinv(a) | |
implicit none | 242 | 242 | implicit none | |
complex(kind=dp_kind),dimension(:,:),intent(in) :: a | 243 | 243 | complex(kind=dp_kind),dimension(:,:),intent(in) :: a | |
complex(kind=dp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_z_matinv,tmp_array | 244 | 244 | complex(kind=dp_kind),dimension(size(a,1),size(a,1)) :: fvn_op_z_matinv,tmp_array | |
call fvn_z_matinv(size(a,1),a,tmp_array,fvn_status) | 245 | 245 | call fvn_z_matinv(size(a,1),a,tmp_array,fvn_status) | |
fvn_op_z_matinv=tmp_array | 246 | 246 | fvn_op_z_matinv=tmp_array | |
end function | 247 | 247 | end function | |
248 | 248 | |||
! | 249 | 249 | ! | |
! .ix. | 250 | 250 | ! .ix. | |
! | 251 | 251 | ! | |
function fvn_op_s_ix(a,b) | 252 | 252 | function fvn_op_s_ix(a,b) | |
implicit none | 253 | 253 | implicit none | |
real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 254 | 254 | real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_s_ix | 255 | 255 | real(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_s_ix | |
fvn_op_s_ix=matmul(fvn_op_s_matinv(a),b) | 256 | 256 | fvn_op_s_ix=matmul(fvn_op_s_matinv(a),b) | |
end function | 257 | 257 | end function | |
function fvn_op_d_ix(a,b) | 258 | 258 | function fvn_op_d_ix(a,b) | |
implicit none | 259 | 259 | implicit none | |
real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 260 | 260 | real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_d_ix | 261 | 261 | real(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_d_ix | |
fvn_op_d_ix=matmul(fvn_op_d_matinv(a),b) | 262 | 262 | fvn_op_d_ix=matmul(fvn_op_d_matinv(a),b) | |
end function | 263 | 263 | end function | |
function fvn_op_c_ix(a,b) | 264 | 264 | function fvn_op_c_ix(a,b) | |
implicit none | 265 | 265 | implicit none | |
complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 266 | 266 | complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_c_ix | 267 | 267 | complex(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_c_ix | |
fvn_op_c_ix=matmul(fvn_op_c_matinv(a),b) | 268 | 268 | fvn_op_c_ix=matmul(fvn_op_c_matinv(a),b) | |
end function | 269 | 269 | end function | |
function fvn_op_z_ix(a,b) | 270 | 270 | function fvn_op_z_ix(a,b) | |
implicit none | 271 | 271 | implicit none | |
complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 272 | 272 | complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_z_ix | 273 | 273 | complex(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_z_ix | |
fvn_op_z_ix=matmul(fvn_op_z_matinv(a),b) | 274 | 274 | fvn_op_z_ix=matmul(fvn_op_z_matinv(a),b) | |
end function | 275 | 275 | end function | |
276 | 276 | |||
! | 277 | 277 | ! | |
! .xi. | 278 | 278 | ! .xi. | |
! | 279 | 279 | ! | |
function fvn_op_s_xi(a,b) | 280 | 280 | function fvn_op_s_xi(a,b) | |
implicit none | 281 | 281 | implicit none | |
real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 282 | 282 | real(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_s_xi | 283 | 283 | real(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_s_xi | |
fvn_op_s_xi=matmul(a,fvn_op_s_matinv(b)) | 284 | 284 | fvn_op_s_xi=matmul(a,fvn_op_s_matinv(b)) | |
end function | 285 | 285 | end function | |
function fvn_op_d_xi(a,b) | 286 | 286 | function fvn_op_d_xi(a,b) | |
implicit none | 287 | 287 | implicit none | |
real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 288 | 288 | real(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
real(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_d_xi | 289 | 289 | real(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_d_xi | |
fvn_op_d_xi=matmul(a,fvn_op_d_matinv(b)) | 290 | 290 | fvn_op_d_xi=matmul(a,fvn_op_d_matinv(b)) | |
end function | 291 | 291 | end function | |
function fvn_op_c_xi(a,b) | 292 | 292 | function fvn_op_c_xi(a,b) | |
implicit none | 293 | 293 | implicit none | |
complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 294 | 294 | complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_c_xi | 295 | 295 | complex(kind=sp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_c_xi | |
fvn_op_c_xi=matmul(a,fvn_op_c_matinv(b)) | 296 | 296 | fvn_op_c_xi=matmul(a,fvn_op_c_matinv(b)) | |
end function | 297 | 297 | end function | |
function fvn_op_z_xi(a,b) | 298 | 298 | function fvn_op_z_xi(a,b) | |
implicit none | 299 | 299 | implicit none | |
complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 300 | 300 | complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_z_xi | 301 | 301 | complex(kind=dp_kind), dimension(size(a,1),size(b,2)) :: fvn_op_z_xi | |
fvn_op_z_xi=matmul(a,fvn_op_z_matinv(b)) | 302 | 302 | fvn_op_z_xi=matmul(a,fvn_op_z_matinv(b)) | |
end function | 303 | 303 | end function | |
304 | 304 | |||
! | 305 | 305 | ! | |
! .h. | 306 | 306 | ! .h. | |
! | 307 | 307 | ! | |
function fvn_op_c_conj_transpose(a) | 308 | 308 | function fvn_op_c_conj_transpose(a) | |
implicit none | 309 | 309 | implicit none | |
complex(kind=sp_kind),dimension(:,:),intent(in) :: a | 310 | 310 | complex(kind=sp_kind),dimension(:,:),intent(in) :: a | |
complex(kind=sp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_c_conj_transpose | 311 | 311 | complex(kind=sp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_c_conj_transpose | |
fvn_op_c_conj_transpose=transpose(conjg(a)) | 312 | 312 | fvn_op_c_conj_transpose=transpose(conjg(a)) | |
end function | 313 | 313 | end function | |
function fvn_op_z_conj_transpose(a) | 314 | 314 | function fvn_op_z_conj_transpose(a) | |
implicit none | 315 | 315 | implicit none | |
complex(kind=dp_kind),dimension(:,:),intent(in) :: a | 316 | 316 | complex(kind=dp_kind),dimension(:,:),intent(in) :: a | |
complex(kind=dp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_z_conj_transpose | 317 | 317 | complex(kind=dp_kind),dimension(size(a,2),size(a,1)) :: fvn_op_z_conj_transpose | |
fvn_op_z_conj_transpose=transpose(conjg(a)) | 318 | 318 | fvn_op_z_conj_transpose=transpose(conjg(a)) | |
end function | 319 | 319 | end function | |
320 | 320 | |||
321 | 321 | |||
! | 322 | 322 | ! | |
! .hx. | 323 | 323 | ! .hx. | |
! | 324 | 324 | ! | |
function fvn_op_c_hx(a,b) | 325 | 325 | function fvn_op_c_hx(a,b) | |
implicit none | 326 | 326 | implicit none | |
complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 327 | 327 | complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=sp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_c_hx | 328 | 328 | complex(kind=sp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_c_hx | |
fvn_op_c_hx=matmul(transpose(conjg(a)),b) | 329 | 329 | fvn_op_c_hx=matmul(transpose(conjg(a)),b) | |
end function | 330 | 330 | end function | |
function fvn_op_z_hx(a,b) | 331 | 331 | function fvn_op_z_hx(a,b) | |
implicit none | 332 | 332 | implicit none | |
complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 333 | 333 | complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=dp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_z_hx | 334 | 334 | complex(kind=dp_kind), dimension(size(a,2),size(b,2)) :: fvn_op_z_hx | |
fvn_op_z_hx=matmul(transpose(conjg(a)),b) | 335 | 335 | fvn_op_z_hx=matmul(transpose(conjg(a)),b) | |
end function | 336 | 336 | end function | |
337 | 337 | |||
338 | 338 | |||
! | 339 | 339 | ! | |
! .xh. | 340 | 340 | ! .xh. | |
! | 341 | 341 | ! | |
function fvn_op_c_xh(a,b) | 342 | 342 | function fvn_op_c_xh(a,b) | |
implicit none | 343 | 343 | implicit none | |
complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | 344 | 344 | complex(kind=sp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=sp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_c_xh | 345 | 345 | complex(kind=sp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_c_xh | |
fvn_op_c_xh=matmul(a,transpose(conjg(b))) | 346 | 346 | fvn_op_c_xh=matmul(a,transpose(conjg(b))) | |
end function | 347 | 347 | end function | |
function fvn_op_z_xh(a,b) | 348 | 348 | function fvn_op_z_xh(a,b) | |
implicit none | 349 | 349 | implicit none | |
complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | 350 | 350 | complex(kind=dp_kind), dimension(:,:), intent(in) :: a,b | |
complex(kind=dp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_z_xh | 351 | 351 | complex(kind=dp_kind), dimension(size(a,1),size(b,1)) :: fvn_op_z_xh | |
fvn_op_z_xh=matmul(a,transpose(conjg(b))) | 352 | 352 | fvn_op_z_xh=matmul(a,transpose(conjg(b))) | |
end function | 353 | 353 | end function | |
354 | 354 | |||
355 | 355 | |||
356 | 356 | |||
357 | 357 | |||
358 | 358 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 359 | 359 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 360 | 360 | ! | |
! Identity Matrix | 361 | 361 | ! Identity Matrix | |
! | 362 | 362 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 363 | 363 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
function fvn_d_ident(n) | 364 | 364 | function fvn_d_ident(n) | |
implicit none | 365 | 365 | implicit none | |
integer(kind=ip_kind) :: n | 366 | 366 | integer(kind=ip_kind) :: n | |
real(kind=dp_kind), dimension(n,n) :: fvn_d_ident | 367 | 367 | real(kind=dp_kind), dimension(n,n) :: fvn_d_ident | |
368 | 368 | |||
real(kind=dp_kind),dimension(n*n) :: vect | 369 | 369 | real(kind=dp_kind),dimension(n*n) :: vect | |
integer(kind=ip_kind) :: i | 370 | 370 | integer(kind=ip_kind) :: i | |
371 | 371 | |||
vect=0._dp_kind | 372 | 372 | vect=0._dp_kind | |
vect(1:n*n:n+1) = 1._dp_kind | 373 | 373 | vect(1:n*n:n+1) = 1._dp_kind | |
fvn_d_ident=reshape(vect, shape = (/ n,n /)) | 374 | 374 | fvn_d_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 375 | 375 | end function | |
376 | 376 | |||
function fvn_s_ident(n) | 377 | 377 | function fvn_s_ident(n) | |
implicit none | 378 | 378 | implicit none | |
integer(kind=ip_kind) :: n | 379 | 379 | integer(kind=ip_kind) :: n | |
real(kind=sp_kind), dimension(n,n) :: fvn_s_ident | 380 | 380 | real(kind=sp_kind), dimension(n,n) :: fvn_s_ident | |
381 | 381 | |||
real(kind=sp_kind),dimension(n*n) :: vect | 382 | 382 | real(kind=sp_kind),dimension(n*n) :: vect | |
integer(kind=ip_kind) :: i | 383 | 383 | integer(kind=ip_kind) :: i | |
384 | 384 | |||
vect=0._sp_kind | 385 | 385 | vect=0._sp_kind | |
vect(1:n*n:n+1) = 1._sp_kind | 386 | 386 | vect(1:n*n:n+1) = 1._sp_kind | |
fvn_s_ident=reshape(vect, shape = (/ n,n /)) | 387 | 387 | fvn_s_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 388 | 388 | end function | |
389 | 389 | |||
function fvn_c_ident(n) | 390 | 390 | function fvn_c_ident(n) | |
implicit none | 391 | 391 | implicit none | |
integer(kind=ip_kind) :: n | 392 | 392 | integer(kind=ip_kind) :: n | |
complex(kind=sp_kind), dimension(n,n) :: fvn_c_ident | 393 | 393 | complex(kind=sp_kind), dimension(n,n) :: fvn_c_ident | |
394 | 394 | |||
complex(kind=sp_kind),dimension(n*n) :: vect | 395 | 395 | complex(kind=sp_kind),dimension(n*n) :: vect | |
integer(kind=ip_kind) :: i | 396 | 396 | integer(kind=ip_kind) :: i | |
397 | 397 | |||
vect=(0._sp_kind,0._sp_kind) | 398 | 398 | vect=(0._sp_kind,0._sp_kind) | |
vect(1:n*n:n+1) = (1._sp_kind,0._sp_kind) | 399 | 399 | vect(1:n*n:n+1) = (1._sp_kind,0._sp_kind) | |
fvn_c_ident=reshape(vect, shape = (/ n,n /)) | 400 | 400 | fvn_c_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 401 | 401 | end function | |
402 | 402 | |||
function fvn_z_ident(n) | 403 | 403 | function fvn_z_ident(n) | |
implicit none | 404 | 404 | implicit none | |
integer(kind=ip_kind) :: n | 405 | 405 | integer(kind=ip_kind) :: n | |
complex(kind=dp_kind), dimension(n,n) :: fvn_z_ident | 406 | 406 | complex(kind=dp_kind), dimension(n,n) :: fvn_z_ident | |
407 | 407 | |||
complex(kind=dp_kind),dimension(n*n) :: vect | 408 | 408 | complex(kind=dp_kind),dimension(n*n) :: vect | |
integer(kind=ip_kind) :: i | 409 | 409 | integer(kind=ip_kind) :: i | |
410 | 410 | |||
vect=(0._dp_kind,0._dp_kind) | 411 | 411 | vect=(0._dp_kind,0._dp_kind) | |
vect(1:n*n:n+1) = (1._dp_kind,0._dp_kind) | 412 | 412 | vect(1:n*n:n+1) = (1._dp_kind,0._dp_kind) | |
fvn_z_ident=reshape(vect, shape = (/ n,n /)) | 413 | 413 | fvn_z_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 414 | 414 | end function | |
415 | 415 | |||
416 | 416 | |||
417 | 417 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 418 | 418 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 419 | 419 | ! | |
! Matrix inversion subroutines | 420 | 420 | ! Matrix inversion subroutines | |
! | 421 | 421 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 422 | 422 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
423 | 423 | |||
subroutine fvn_s_matinv(d,a,inva,status) | 424 | 424 | subroutine fvn_s_matinv(d,a,inva,status) | |
! | 425 | 425 | ! | |
! Matrix inversion of a real(kind=sp_kind) matrix using BLAS and LAPACK | 426 | 426 | ! Matrix inversion of a real(kind=sp_kind) matrix using BLAS and LAPACK | |
! | 427 | 427 | ! | |
! d (in) : matrix rank | 428 | 428 | ! d (in) : matrix rank | |
! a (in) : input matrix | 429 | 429 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 430 | 430 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 431 | 431 | ! status (ou) : =0 if something failed | |
! | 432 | 432 | ! | |
implicit none | 433 | 433 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 434 | 434 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=sp_kind), intent(in) :: a(d,d) | 435 | 435 | real(kind=sp_kind), intent(in) :: a(d,d) | |
real(kind=sp_kind), intent(out) :: inva(d,d) | 436 | 436 | real(kind=sp_kind), intent(out) :: inva(d,d) | |
integer(kind=ip_kind), intent(out),optional :: status | 437 | 437 | integer(kind=ip_kind), intent(out),optional :: status | |
438 | 438 | |||
integer(kind=ip_kind), allocatable :: ipiv(:) | 439 | 439 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
real(kind=sp_kind), allocatable :: work(:) | 440 | 440 | real(kind=sp_kind), allocatable :: work(:) | |
real(kind=sp_kind) twork(1) | 441 | 441 | real(kind=sp_kind) twork(1) | |
integer(kind=ip_kind) :: info | 442 | 442 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 443 | 443 | integer(kind=ip_kind) :: lwork | |
444 | 444 | |||
if (present(status)) status=1 | 445 | 445 | if (present(status)) status=1 | |
446 | 446 | |||
allocate(ipiv(d)) | 447 | 447 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 448 | 448 | ! copy a into inva using BLAS | |
!call scopy(d*d,a,1,inva,1) | 449 | 449 | !call scopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 450 | 450 | inva(:,:)=a(:,:) | |
! LU factorization using LAPACK | 451 | 451 | ! LU factorization using LAPACK | |
call sgetrf(d,d,inva,d,ipiv,info) | 452 | 452 | call sgetrf(d,d,inva,d,ipiv,info) | |
! if info is not equal to 0, something went wrong we exit setting status to 0 | 453 | 453 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 454 | 454 | if (info /= 0) then | |
if (present(status)) status=0 | 455 | 455 | if (present(status)) status=0 | |
deallocate(ipiv) | 456 | 456 | deallocate(ipiv) | |
return | 457 | 457 | return | |
end if | 458 | 458 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 459 | 459 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call sgetri(d,inva,d,ipiv,twork,-1,info) | 460 | 460 | call sgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 461 | 461 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 462 | 462 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 463 | 463 | ! Matrix inversion using LAPACK | |
call sgetri(d,inva,d,ipiv,work,lwork,info) | 464 | 464 | call sgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 465 | 465 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 466 | 466 | if (info /= 0) then | |
if (present(status)) status=0 | 467 | 467 | if (present(status)) status=0 | |
end if | 468 | 468 | end if | |
deallocate(work) | 469 | 469 | deallocate(work) | |
deallocate(ipiv) | 470 | 470 | deallocate(ipiv) | |
end subroutine | 471 | 471 | end subroutine | |
472 | 472 | |||
subroutine fvn_d_matinv(d,a,inva,status) | 473 | 473 | subroutine fvn_d_matinv(d,a,inva,status) | |
! | 474 | 474 | ! | |
! Matrix inversion of a real(kind=dp_kind) matrix using BLAS and LAPACK | 475 | 475 | ! Matrix inversion of a real(kind=dp_kind) matrix using BLAS and LAPACK | |
! | 476 | 476 | ! | |
! d (in) : matrix rank | 477 | 477 | ! d (in) : matrix rank | |
! a (in) : input matrix | 478 | 478 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 479 | 479 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 480 | 480 | ! status (ou) : =0 if something failed | |
! | 481 | 481 | ! | |
implicit none | 482 | 482 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 483 | 483 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=dp_kind), intent(in) :: a(d,d) | 484 | 484 | real(kind=dp_kind), intent(in) :: a(d,d) | |
real(kind=dp_kind), intent(out) :: inva(d,d) | 485 | 485 | real(kind=dp_kind), intent(out) :: inva(d,d) | |
integer(kind=ip_kind), intent(out),optional :: status | 486 | 486 | integer(kind=ip_kind), intent(out),optional :: status | |
487 | 487 | |||
integer(kind=ip_kind), allocatable :: ipiv(:) | 488 | 488 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
real(kind=dp_kind), allocatable :: work(:) | 489 | 489 | real(kind=dp_kind), allocatable :: work(:) | |
real(kind=dp_kind) :: twork(1) | 490 | 490 | real(kind=dp_kind) :: twork(1) | |
integer(kind=ip_kind) :: info | 491 | 491 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 492 | 492 | integer(kind=ip_kind) :: lwork | |
493 | 493 | |||
if (present(status)) status=1 | 494 | 494 | if (present(status)) status=1 | |
495 | 495 | |||
allocate(ipiv(d)) | 496 | 496 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 497 | 497 | ! copy a into inva using BLAS | |
!call dcopy(d*d,a,1,inva,1) | 498 | 498 | !call dcopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 499 | 499 | inva(:,:)=a(:,:) | |
! LU factorization using LAPACK | 500 | 500 | ! LU factorization using LAPACK | |
call dgetrf(d,d,inva,d,ipiv,info) | 501 | 501 | call dgetrf(d,d,inva,d,ipiv,info) | |
! if info is not equal to 0, something went wrong we exit setting status to 0 | 502 | 502 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 503 | 503 | if (info /= 0) then | |
if (present(status)) status=0 | 504 | 504 | if (present(status)) status=0 | |
deallocate(ipiv) | 505 | 505 | deallocate(ipiv) | |
return | 506 | 506 | return | |
end if | 507 | 507 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 508 | 508 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call dgetri(d,inva,d,ipiv,twork,-1,info) | 509 | 509 | call dgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 510 | 510 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 511 | 511 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 512 | 512 | ! Matrix inversion using LAPACK | |
call dgetri(d,inva,d,ipiv,work,lwork,info) | 513 | 513 | call dgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 514 | 514 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 515 | 515 | if (info /= 0) then | |
if (present(status)) status=0 | 516 | 516 | if (present(status)) status=0 | |
end if | 517 | 517 | end if | |
deallocate(work) | 518 | 518 | deallocate(work) | |
deallocate(ipiv) | 519 | 519 | deallocate(ipiv) | |
end subroutine | 520 | 520 | end subroutine | |
521 | 521 | |||
subroutine fvn_c_matinv(d,a,inva,status) | 522 | 522 | subroutine fvn_c_matinv(d,a,inva,status) | |
! | 523 | 523 | ! | |
! Matrix inversion of a complex(kind=sp_kind) matrix using BLAS and LAPACK | 524 | 524 | ! Matrix inversion of a complex(kind=sp_kind) matrix using BLAS and LAPACK | |
! | 525 | 525 | ! | |
! d (in) : matrix rank | 526 | 526 | ! d (in) : matrix rank | |
! a (in) : input matrix | 527 | 527 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 528 | 528 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 529 | 529 | ! status (ou) : =0 if something failed | |
! | 530 | 530 | ! | |
implicit none | 531 | 531 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 532 | 532 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=sp_kind), intent(in) :: a(d,d) | 533 | 533 | complex(kind=sp_kind), intent(in) :: a(d,d) | |
complex(kind=sp_kind), intent(out) :: inva(d,d) | 534 | 534 | complex(kind=sp_kind), intent(out) :: inva(d,d) | |
integer(kind=ip_kind), intent(out),optional :: status | 535 | 535 | integer(kind=ip_kind), intent(out),optional :: status | |
536 | 536 | |||
integer(kind=ip_kind), allocatable :: ipiv(:) | 537 | 537 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
complex(kind=sp_kind), allocatable :: work(:) | 538 | 538 | complex(kind=sp_kind), allocatable :: work(:) | |
complex(kind=sp_kind) :: twork(1) | 539 | 539 | complex(kind=sp_kind) :: twork(1) | |
integer(kind=ip_kind) :: info | 540 | 540 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 541 | 541 | integer(kind=ip_kind) :: lwork | |
542 | 542 | |||
if (present(status)) status=1 | 543 | 543 | if (present(status)) status=1 | |
544 | 544 | |||
allocate(ipiv(d)) | 545 | 545 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 546 | 546 | ! copy a into inva using BLAS | |
!call ccopy(d*d,a,1,inva,1) | 547 | 547 | !call ccopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 548 | 548 | inva(:,:)=a(:,:) | |
549 | 549 | |||
! LU factorization using LAPACK | 550 | 550 | ! LU factorization using LAPACK | |
call cgetrf(d,d,inva,d,ipiv,info) | 551 | 551 | call cgetrf(d,d,inva,d,ipiv,info) | |
! if info is not equal to 0, something went wrong we exit setting status to 0 | 552 | 552 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 553 | 553 | if (info /= 0) then | |
if (present(status)) status=0 | 554 | 554 | if (present(status)) status=0 | |
deallocate(ipiv) | 555 | 555 | deallocate(ipiv) | |
return | 556 | 556 | return | |
end if | 557 | 557 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 558 | 558 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call cgetri(d,inva,d,ipiv,twork,-1,info) | 559 | 559 | call cgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 560 | 560 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 561 | 561 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 562 | 562 | ! Matrix inversion using LAPACK | |
call cgetri(d,inva,d,ipiv,work,lwork,info) | 563 | 563 | call cgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 564 | 564 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 565 | 565 | if (info /= 0) then | |
if (present(status)) status=0 | 566 | 566 | if (present(status)) status=0 | |
end if | 567 | 567 | end if | |
deallocate(work) | 568 | 568 | deallocate(work) | |
deallocate(ipiv) | 569 | 569 | deallocate(ipiv) | |
end subroutine | 570 | 570 | end subroutine | |
571 | 571 | |||
subroutine fvn_z_matinv(d,a,inva,status) | 572 | 572 | subroutine fvn_z_matinv(d,a,inva,status) | |
! | 573 | 573 | ! | |
! Matrix inversion of a complex(kind=dp_kind)(kind=sp_kind) matrix using BLAS and LAPACK | 574 | 574 | ! Matrix inversion of a complex(kind=dp_kind)(kind=sp_kind) matrix using BLAS and LAPACK | |
! | 575 | 575 | ! | |
! d (in) : matrix rank | 576 | 576 | ! d (in) : matrix rank | |
! a (in) : input matrix | 577 | 577 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 578 | 578 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 579 | 579 | ! status (ou) : =0 if something failed | |
! | 580 | 580 | ! | |
implicit none | 581 | 581 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 582 | 582 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=dp_kind), intent(in) :: a(d,d) | 583 | 583 | complex(kind=dp_kind), intent(in) :: a(d,d) | |
complex(kind=dp_kind), intent(out) :: inva(d,d) | 584 | 584 | complex(kind=dp_kind), intent(out) :: inva(d,d) | |
integer(kind=ip_kind), intent(out),optional :: status | 585 | 585 | integer(kind=ip_kind), intent(out),optional :: status | |
586 | 586 | |||
integer(kind=ip_kind), allocatable :: ipiv(:) | 587 | 587 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
complex(kind=dp_kind), allocatable :: work(:) | 588 | 588 | complex(kind=dp_kind), allocatable :: work(:) | |
complex(kind=dp_kind) :: twork(1) | 589 | 589 | complex(kind=dp_kind) :: twork(1) | |
integer(kind=ip_kind) :: info | 590 | 590 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 591 | 591 | integer(kind=ip_kind) :: lwork | |
592 | 592 | |||
if (present(status)) status=1 | 593 | 593 | if (present(status)) status=1 | |
594 | 594 | |||
allocate(ipiv(d)) | 595 | 595 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 596 | 596 | ! copy a into inva using BLAS | |
!call zcopy(d*d,a,1,inva,1) | 597 | 597 | !call zcopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 598 | 598 | inva(:,:)=a(:,:) | |
599 | 599 | |||
! LU factorization using LAPACK | 600 | 600 | ! LU factorization using LAPACK | |
call zgetrf(d,d,inva,d,ipiv,info) | 601 | 601 | call zgetrf(d,d,inva,d,ipiv,info) | |
! if info is not equal to 0, something went wrong we exit setting status to 0 | 602 | 602 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 603 | 603 | if (info /= 0) then | |
if (present(status)) status=0 | 604 | 604 | if (present(status)) status=0 | |
deallocate(ipiv) | 605 | 605 | deallocate(ipiv) | |
return | 606 | 606 | return | |
end if | 607 | 607 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 608 | 608 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call zgetri(d,inva,d,ipiv,twork,-1,info) | 609 | 609 | call zgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 610 | 610 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 611 | 611 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 612 | 612 | ! Matrix inversion using LAPACK | |
call zgetri(d,inva,d,ipiv,work,lwork,info) | 613 | 613 | call zgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 614 | 614 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 615 | 615 | if (info /= 0) then | |
if (present(status)) status=0 | 616 | 616 | if (present(status)) status=0 | |
end if | 617 | 617 | end if | |
deallocate(work) | 618 | 618 | deallocate(work) | |
deallocate(ipiv) | 619 | 619 | deallocate(ipiv) | |
end subroutine | 620 | 620 | end subroutine | |
621 | 621 | |||
622 | 622 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 623 | 623 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 624 | 624 | ! | |
! Determinants | 625 | 625 | ! Determinants | |
! | 626 | 626 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 627 | 627 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
function fvn_s_det(d,a,status) | 628 | 628 | function fvn_s_det(d,a,status) | |
! | 629 | 629 | ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 630 | 630 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 631 | 631 | ! | |
! d (in) : matrix rank | 632 | 632 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 633 | 633 | ! a (in) : The Matrix | |
! status (out) : =0 if LU factorization failed | 634 | 634 | ! status (out) : =0 if LU factorization failed | |
! | 635 | 635 | ! | |
implicit none | 636 | 636 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 637 | 637 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=sp_kind), intent(in) :: a(d,d) | 638 | 638 | real(kind=sp_kind), intent(in) :: a(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 639 | 639 | integer(kind=ip_kind), intent(out), optional :: status | |
real(kind=sp_kind) :: fvn_s_det | 640 | 640 | real(kind=sp_kind) :: fvn_s_det | |
641 | 641 | |||
real(kind=sp_kind), allocatable :: wc_a(:,:) | 642 | 642 | real(kind=sp_kind), allocatable :: wc_a(:,:) | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 643 | 643 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
integer(kind=ip_kind) :: info,i | 644 | 644 | integer(kind=ip_kind) :: info,i | |
645 | 645 | |||
if (present(status)) status=1 | 646 | 646 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 647 | 647 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 648 | 648 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 649 | 649 | wc_a(:,:)=a(:,:) | |
call sgetrf(d,d,wc_a,d,ipiv,info) | 650 | 650 | call sgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 651 | 651 | if (info/= 0) then | |
if (present(status)) status=0 | 652 | 652 | if (present(status)) status=0 | |
fvn_s_det=0.e0 | 653 | 653 | fvn_s_det=0.e0 | |
deallocate(ipiv) | 654 | 654 | deallocate(ipiv) | |
deallocate(wc_a) | 655 | 655 | deallocate(wc_a) | |
return | 656 | 656 | return | |
end if | 657 | 657 | end if | |
fvn_s_det=1.e0 | 658 | 658 | fvn_s_det=1.e0 | |
do i=1,d | 659 | 659 | do i=1,d | |
if (ipiv(i)==i) then | 660 | 660 | if (ipiv(i)==i) then | |
fvn_s_det=fvn_s_det*wc_a(i,i) | 661 | 661 | fvn_s_det=fvn_s_det*wc_a(i,i) | |
else | 662 | 662 | else | |
fvn_s_det=-fvn_s_det*wc_a(i,i) | 663 | 663 | fvn_s_det=-fvn_s_det*wc_a(i,i) | |
end if | 664 | 664 | end if | |
end do | 665 | 665 | end do | |
deallocate(ipiv) | 666 | 666 | deallocate(ipiv) | |
deallocate(wc_a) | 667 | 667 | deallocate(wc_a) | |
668 | 668 | |||
end function | 669 | 669 | end function | |
670 | 670 | |||
function fvn_d_det(d,a,status) | 671 | 671 | function fvn_d_det(d,a,status) | |
! | 672 | 672 | ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 673 | 673 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 674 | 674 | ! | |
! d (in) : matrix rank | 675 | 675 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 676 | 676 | ! a (in) : The Matrix | |
! status (out) : =0 if LU factorization failed | 677 | 677 | ! status (out) : =0 if LU factorization failed | |
! | 678 | 678 | ! | |
implicit none | 679 | 679 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 680 | 680 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=dp_kind), intent(in) :: a(d,d) | 681 | 681 | real(kind=dp_kind), intent(in) :: a(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 682 | 682 | integer(kind=ip_kind), intent(out), optional :: status | |
real(kind=dp_kind) :: fvn_d_det | 683 | 683 | real(kind=dp_kind) :: fvn_d_det | |
684 | 684 | |||
real(kind=dp_kind), allocatable :: wc_a(:,:) | 685 | 685 | real(kind=dp_kind), allocatable :: wc_a(:,:) | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 686 | 686 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
integer(kind=ip_kind) :: info,i | 687 | 687 | integer(kind=ip_kind) :: info,i | |
688 | 688 | |||
if (present(status)) status=1 | 689 | 689 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 690 | 690 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 691 | 691 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 692 | 692 | wc_a(:,:)=a(:,:) | |
call dgetrf(d,d,wc_a,d,ipiv,info) | 693 | 693 | call dgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 694 | 694 | if (info/= 0) then | |
if (present(status)) status=0 | 695 | 695 | if (present(status)) status=0 | |
fvn_d_det=0.d0 | 696 | 696 | fvn_d_det=0.d0 | |
deallocate(ipiv) | 697 | 697 | deallocate(ipiv) | |
deallocate(wc_a) | 698 | 698 | deallocate(wc_a) | |
return | 699 | 699 | return | |
end if | 700 | 700 | end if | |
fvn_d_det=1.d0 | 701 | 701 | fvn_d_det=1.d0 | |
do i=1,d | 702 | 702 | do i=1,d | |
if (ipiv(i)==i) then | 703 | 703 | if (ipiv(i)==i) then | |
fvn_d_det=fvn_d_det*wc_a(i,i) | 704 | 704 | fvn_d_det=fvn_d_det*wc_a(i,i) | |
else | 705 | 705 | else | |
fvn_d_det=-fvn_d_det*wc_a(i,i) | 706 | 706 | fvn_d_det=-fvn_d_det*wc_a(i,i) | |
end if | 707 | 707 | end if | |
end do | 708 | 708 | end do | |
deallocate(ipiv) | 709 | 709 | deallocate(ipiv) | |
deallocate(wc_a) | 710 | 710 | deallocate(wc_a) | |
711 | 711 | |||
end function | 712 | 712 | end function | |
713 | 713 | |||
function fvn_c_det(d,a,status) ! | 714 | 714 | function fvn_c_det(d,a,status) ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 715 | 715 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 716 | 716 | ! | |
! d (in) : matrix rank | 717 | 717 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 718 | 718 | ! a (in) : The Matrix | |
! status (out) : =0 if LU factorization failed | 719 | 719 | ! status (out) : =0 if LU factorization failed | |
! | 720 | 720 | ! | |
implicit none | 721 | 721 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 722 | 722 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=sp_kind), intent(in) :: a(d,d) | 723 | 723 | complex(kind=sp_kind), intent(in) :: a(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 724 | 724 | integer(kind=ip_kind), intent(out), optional :: status | |
complex(kind=sp_kind) :: fvn_c_det | 725 | 725 | complex(kind=sp_kind) :: fvn_c_det | |
726 | 726 | |||
complex(kind=sp_kind), allocatable :: wc_a(:,:) | 727 | 727 | complex(kind=sp_kind), allocatable :: wc_a(:,:) | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 728 | 728 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
integer(kind=ip_kind) :: info,i | 729 | 729 | integer(kind=ip_kind) :: info,i | |
730 | 730 | |||
if (present(status)) status=1 | 731 | 731 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 732 | 732 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 733 | 733 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 734 | 734 | wc_a(:,:)=a(:,:) | |
call cgetrf(d,d,wc_a,d,ipiv,info) | 735 | 735 | call cgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 736 | 736 | if (info/= 0) then | |
if (present(status)) status=0 | 737 | 737 | if (present(status)) status=0 | |
fvn_c_det=(0.e0,0.e0) | 738 | 738 | fvn_c_det=(0.e0,0.e0) | |
deallocate(ipiv) | 739 | 739 | deallocate(ipiv) | |
deallocate(wc_a) | 740 | 740 | deallocate(wc_a) | |
return | 741 | 741 | return | |
end if | 742 | 742 | end if | |
fvn_c_det=(1.e0,0.e0) | 743 | 743 | fvn_c_det=(1.e0,0.e0) | |
do i=1,d | 744 | 744 | do i=1,d | |
if (ipiv(i)==i) then | 745 | 745 | if (ipiv(i)==i) then | |
fvn_c_det=fvn_c_det*wc_a(i,i) | 746 | 746 | fvn_c_det=fvn_c_det*wc_a(i,i) | |
else | 747 | 747 | else | |
fvn_c_det=-fvn_c_det*wc_a(i,i) | 748 | 748 | fvn_c_det=-fvn_c_det*wc_a(i,i) | |
end if | 749 | 749 | end if | |
end do | 750 | 750 | end do | |
deallocate(ipiv) | 751 | 751 | deallocate(ipiv) | |
deallocate(wc_a) | 752 | 752 | deallocate(wc_a) | |
753 | 753 | |||
end function | 754 | 754 | end function | |
755 | 755 | |||
function fvn_z_det(d,a,status) | 756 | 756 | function fvn_z_det(d,a,status) | |
! | 757 | 757 | ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 758 | 758 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 759 | 759 | ! | |
! d (in) : matrix rank | 760 | 760 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 761 | 761 | ! a (in) : The Matrix | |
! det (out) : determinant | 762 | 762 | ! det (out) : determinant | |
! status (out) : =0 if LU factorization failed | 763 | 763 | ! status (out) : =0 if LU factorization failed | |
! | 764 | 764 | ! | |
implicit none | 765 | 765 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 766 | 766 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=dp_kind), intent(in) :: a(d,d) | 767 | 767 | complex(kind=dp_kind), intent(in) :: a(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 768 | 768 | integer(kind=ip_kind), intent(out), optional :: status | |
complex(kind=dp_kind) :: fvn_z_det | 769 | 769 | complex(kind=dp_kind) :: fvn_z_det | |
770 | 770 | |||
complex(kind=dp_kind), allocatable :: wc_a(:,:) | 771 | 771 | complex(kind=dp_kind), allocatable :: wc_a(:,:) | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 772 | 772 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
integer(kind=ip_kind) :: info,i | 773 | 773 | integer(kind=ip_kind) :: info,i | |
774 | 774 | |||
if (present(status)) status=1 | 775 | 775 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 776 | 776 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 777 | 777 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 778 | 778 | wc_a(:,:)=a(:,:) | |
call zgetrf(d,d,wc_a,d,ipiv,info) | 779 | 779 | call zgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 780 | 780 | if (info/= 0) then | |
if (present(status)) status=0 | 781 | 781 | if (present(status)) status=0 | |
fvn_z_det=(0.d0,0.d0) | 782 | 782 | fvn_z_det=(0.d0,0.d0) | |
deallocate(ipiv) | 783 | 783 | deallocate(ipiv) | |
deallocate(wc_a) | 784 | 784 | deallocate(wc_a) | |
return | 785 | 785 | return | |
end if | 786 | 786 | end if | |
fvn_z_det=(1.d0,0.d0) | 787 | 787 | fvn_z_det=(1.d0,0.d0) | |
do i=1,d | 788 | 788 | do i=1,d | |
if (ipiv(i)==i) then | 789 | 789 | if (ipiv(i)==i) then | |
fvn_z_det=fvn_z_det*wc_a(i,i) | 790 | 790 | fvn_z_det=fvn_z_det*wc_a(i,i) | |
else | 791 | 791 | else | |
fvn_z_det=-fvn_z_det*wc_a(i,i) | 792 | 792 | fvn_z_det=-fvn_z_det*wc_a(i,i) | |
end if | 793 | 793 | end if | |
end do | 794 | 794 | end do | |
deallocate(ipiv) | 795 | 795 | deallocate(ipiv) | |
deallocate(wc_a) | 796 | 796 | deallocate(wc_a) | |
797 | 797 | |||
end function | 798 | 798 | end function | |
799 | 799 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 800 | 800 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 801 | 801 | ! | |
! Condition test | 802 | 802 | ! Condition test | |
! | 803 | 803 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 804 | 804 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! 1-norm | 805 | 805 | ! 1-norm | |
! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm | 806 | 806 | ! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm | |
! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond | 807 | 807 | ! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond | |
! | 808 | 808 | ! | |
subroutine fvn_s_matcon(d,a,rcond,status) | 809 | 809 | subroutine fvn_s_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 810 | 810 | ! Matrix condition (reciprocal of condition number) | |
! | 811 | 811 | ! | |
! d (in) : matrix rank | 812 | 812 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 813 | 813 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 814 | 814 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 815 | 815 | ! status (out) : =0 if something went wrong | |
! | 816 | 816 | ! | |
implicit none | 817 | 817 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 818 | 818 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=sp_kind), intent(in) :: a(d,d) | 819 | 819 | real(kind=sp_kind), intent(in) :: a(d,d) | |
real(kind=sp_kind), intent(out) :: rcond | 820 | 820 | real(kind=sp_kind), intent(out) :: rcond | |
integer(kind=ip_kind), intent(out), optional :: status | 821 | 821 | integer(kind=ip_kind), intent(out), optional :: status | |
822 | 822 | |||
real(kind=sp_kind), allocatable :: work(:) | 823 | 823 | real(kind=sp_kind), allocatable :: work(:) | |
integer(kind=ip_kind), allocatable :: iwork(:) | 824 | 824 | integer(kind=ip_kind), allocatable :: iwork(:) | |
real(kind=sp_kind) :: anorm | 825 | 825 | real(kind=sp_kind) :: anorm | |
real(kind=sp_kind), allocatable :: wc_a(:,:) ! working copy of a | 826 | 826 | real(kind=sp_kind), allocatable :: wc_a(:,:) ! working copy of a | |
integer(kind=ip_kind) :: info | 827 | 827 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 828 | 828 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
829 | 829 | |||
real(kind=sp_kind), external :: slange | 830 | 830 | real(kind=sp_kind), external :: slange | |
831 | 831 | |||
832 | 832 | |||
if (present(status)) status=1 | 833 | 833 | if (present(status)) status=1 | |
834 | 834 | |||
anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | 835 | 835 | anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | |
836 | 836 | |||
allocate(wc_a(d,d)) | 837 | 837 | allocate(wc_a(d,d)) | |
!call scopy(d*d,a,1,wc_a,1) | 838 | 838 | !call scopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 839 | 839 | wc_a(:,:)=a(:,:) | |
840 | 840 | |||
allocate(ipiv(d)) | 841 | 841 | allocate(ipiv(d)) | |
call sgetrf(d,d,wc_a,d,ipiv,info) | 842 | 842 | call sgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 843 | 843 | if (info /= 0) then | |
if (present(status)) status=0 | 844 | 844 | if (present(status)) status=0 | |
deallocate(ipiv) | 845 | 845 | deallocate(ipiv) | |
deallocate(wc_a) | 846 | 846 | deallocate(wc_a) | |
return | 847 | 847 | return | |
end if | 848 | 848 | end if | |
allocate(work(4*d)) | 849 | 849 | allocate(work(4*d)) | |
allocate(iwork(d)) | 850 | 850 | allocate(iwork(d)) | |
call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | 851 | 851 | call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | |
if (info /= 0) then | 852 | 852 | if (info /= 0) then | |
if (present(status)) status=0 | 853 | 853 | if (present(status)) status=0 | |
end if | 854 | 854 | end if | |
deallocate(iwork) | 855 | 855 | deallocate(iwork) | |
deallocate(work) | 856 | 856 | deallocate(work) | |
deallocate(ipiv) | 857 | 857 | deallocate(ipiv) | |
deallocate(wc_a) | 858 | 858 | deallocate(wc_a) | |
859 | 859 | |||
end subroutine | 860 | 860 | end subroutine | |
861 | 861 | |||
subroutine fvn_d_matcon(d,a,rcond,status) | 862 | 862 | subroutine fvn_d_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 863 | 863 | ! Matrix condition (reciprocal of condition number) | |
! | 864 | 864 | ! | |
! d (in) : matrix rank | 865 | 865 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 866 | 866 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 867 | 867 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 868 | 868 | ! status (out) : =0 if something went wrong | |
! | 869 | 869 | ! | |
implicit none | 870 | 870 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 871 | 871 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=dp_kind), intent(in) :: a(d,d) | 872 | 872 | real(kind=dp_kind), intent(in) :: a(d,d) | |
real(kind=dp_kind), intent(out) :: rcond | 873 | 873 | real(kind=dp_kind), intent(out) :: rcond | |
integer(kind=ip_kind), intent(out), optional :: status | 874 | 874 | integer(kind=ip_kind), intent(out), optional :: status | |
875 | 875 | |||
real(kind=dp_kind), allocatable :: work(:) | 876 | 876 | real(kind=dp_kind), allocatable :: work(:) | |
integer(kind=ip_kind), allocatable :: iwork(:) | 877 | 877 | integer(kind=ip_kind), allocatable :: iwork(:) | |
real(kind=dp_kind) :: anorm | 878 | 878 | real(kind=dp_kind) :: anorm | |
real(kind=dp_kind), allocatable :: wc_a(:,:) ! working copy of a | 879 | 879 | real(kind=dp_kind), allocatable :: wc_a(:,:) ! working copy of a | |
integer(kind=ip_kind) :: info | 880 | 880 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 881 | 881 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
882 | 882 | |||
real(kind=dp_kind), external :: dlange | 883 | 883 | real(kind=dp_kind), external :: dlange | |
884 | 884 | |||
885 | 885 | |||
if (present(status)) status=1 | 886 | 886 | if (present(status)) status=1 | |
887 | 887 | |||
anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | 888 | 888 | anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | |
889 | 889 | |||
allocate(wc_a(d,d)) | 890 | 890 | allocate(wc_a(d,d)) | |
!call dcopy(d*d,a,1,wc_a,1) | 891 | 891 | !call dcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 892 | 892 | wc_a(:,:)=a(:,:) | |
893 | 893 | |||
allocate(ipiv(d)) | 894 | 894 | allocate(ipiv(d)) | |
call dgetrf(d,d,wc_a,d,ipiv,info) | 895 | 895 | call dgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 896 | 896 | if (info /= 0) then | |
if (present(status)) status=0 | 897 | 897 | if (present(status)) status=0 | |
deallocate(ipiv) | 898 | 898 | deallocate(ipiv) | |
deallocate(wc_a) | 899 | 899 | deallocate(wc_a) | |
return | 900 | 900 | return | |
end if | 901 | 901 | end if | |
902 | 902 | |||
allocate(work(4*d)) | 903 | 903 | allocate(work(4*d)) | |
allocate(iwork(d)) | 904 | 904 | allocate(iwork(d)) | |
call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | 905 | 905 | call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | |
if (info /= 0) then | 906 | 906 | if (info /= 0) then | |
if (present(status)) status=0 | 907 | 907 | if (present(status)) status=0 | |
end if | 908 | 908 | end if | |
deallocate(iwork) | 909 | 909 | deallocate(iwork) | |
deallocate(work) | 910 | 910 | deallocate(work) | |
deallocate(ipiv) | 911 | 911 | deallocate(ipiv) | |
deallocate(wc_a) | 912 | 912 | deallocate(wc_a) | |
913 | 913 | |||
end subroutine | 914 | 914 | end subroutine | |
915 | 915 | |||
subroutine fvn_c_matcon(d,a,rcond,status) | 916 | 916 | subroutine fvn_c_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 917 | 917 | ! Matrix condition (reciprocal of condition number) | |
! | 918 | 918 | ! | |
! d (in) : matrix rank | 919 | 919 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 920 | 920 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 921 | 921 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 922 | 922 | ! status (out) : =0 if something went wrong | |
! | 923 | 923 | ! | |
implicit none | 924 | 924 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 925 | 925 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=sp_kind), intent(in) :: a(d,d) | 926 | 926 | complex(kind=sp_kind), intent(in) :: a(d,d) | |
real(kind=sp_kind), intent(out) :: rcond | 927 | 927 | real(kind=sp_kind), intent(out) :: rcond | |
integer(kind=ip_kind), intent(out), optional :: status | 928 | 928 | integer(kind=ip_kind), intent(out), optional :: status | |
929 | 929 | |||
real(kind=sp_kind), allocatable :: rwork(:) | 930 | 930 | real(kind=sp_kind), allocatable :: rwork(:) | |
complex(kind=sp_kind), allocatable :: work(:) | 931 | 931 | complex(kind=sp_kind), allocatable :: work(:) | |
integer(kind=ip_kind), allocatable :: iwork(:) | 932 | 932 | integer(kind=ip_kind), allocatable :: iwork(:) | |
real(kind=sp_kind) :: anorm | 933 | 933 | real(kind=sp_kind) :: anorm | |
complex(kind=sp_kind), allocatable :: wc_a(:,:) ! working copy of a | 934 | 934 | complex(kind=sp_kind), allocatable :: wc_a(:,:) ! working copy of a | |
integer(kind=ip_kind) :: info | 935 | 935 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 936 | 936 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
937 | 937 | |||
real(kind=sp_kind), external :: clange | 938 | 938 | real(kind=sp_kind), external :: clange | |
939 | 939 | |||
940 | 940 | |||
if (present(status)) status=1 | 941 | 941 | if (present(status)) status=1 | |
942 | 942 | |||
anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | 943 | 943 | anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | |
944 | 944 | |||
allocate(wc_a(d,d)) | 945 | 945 | allocate(wc_a(d,d)) | |
!call ccopy(d*d,a,1,wc_a,1) | 946 | 946 | !call ccopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 947 | 947 | wc_a(:,:)=a(:,:) | |
948 | 948 | |||
allocate(ipiv(d)) | 949 | 949 | allocate(ipiv(d)) | |
call cgetrf(d,d,wc_a,d,ipiv,info) | 950 | 950 | call cgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 951 | 951 | if (info /= 0) then | |
if (present(status)) status=0 | 952 | 952 | if (present(status)) status=0 | |
deallocate(ipiv) | 953 | 953 | deallocate(ipiv) | |
deallocate(wc_a) | 954 | 954 | deallocate(wc_a) | |
return | 955 | 955 | return | |
end if | 956 | 956 | end if | |
allocate(work(2*d)) | 957 | 957 | allocate(work(2*d)) | |
allocate(rwork(2*d)) | 958 | 958 | allocate(rwork(2*d)) | |
call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | 959 | 959 | call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | |
if (info /= 0) then | 960 | 960 | if (info /= 0) then | |
if (present(status)) status=0 | 961 | 961 | if (present(status)) status=0 | |
end if | 962 | 962 | end if | |
deallocate(rwork) | 963 | 963 | deallocate(rwork) | |
deallocate(work) | 964 | 964 | deallocate(work) | |
deallocate(ipiv) | 965 | 965 | deallocate(ipiv) | |
deallocate(wc_a) | 966 | 966 | deallocate(wc_a) | |
end subroutine | 967 | 967 | end subroutine | |
968 | 968 | |||
subroutine fvn_z_matcon(d,a,rcond,status) | 969 | 969 | subroutine fvn_z_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 970 | 970 | ! Matrix condition (reciprocal of condition number) | |
! | 971 | 971 | ! | |
! d (in) : matrix rank | 972 | 972 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 973 | 973 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 974 | 974 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 975 | 975 | ! status (out) : =0 if something went wrong | |
! | 976 | 976 | ! | |
implicit none | 977 | 977 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 978 | 978 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=dp_kind), intent(in) :: a(d,d) | 979 | 979 | complex(kind=dp_kind), intent(in) :: a(d,d) | |
real(kind=dp_kind), intent(out) :: rcond | 980 | 980 | real(kind=dp_kind), intent(out) :: rcond | |
integer(kind=ip_kind), intent(out), optional :: status | 981 | 981 | integer(kind=ip_kind), intent(out), optional :: status | |
982 | 982 | |||
complex(kind=dp_kind), allocatable :: work(:) | 983 | 983 | complex(kind=dp_kind), allocatable :: work(:) | |
real(kind=dp_kind), allocatable :: rwork(:) | 984 | 984 | real(kind=dp_kind), allocatable :: rwork(:) | |
real(kind=dp_kind) :: anorm | 985 | 985 | real(kind=dp_kind) :: anorm | |
complex(kind=dp_kind), allocatable :: wc_a(:,:) ! working copy of a | 986 | 986 | complex(kind=dp_kind), allocatable :: wc_a(:,:) ! working copy of a | |
integer(kind=ip_kind) :: info | 987 | 987 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind), allocatable :: ipiv(:) | 988 | 988 | integer(kind=ip_kind), allocatable :: ipiv(:) | |
989 | 989 | |||
real(kind=dp_kind), external :: zlange | 990 | 990 | real(kind=dp_kind), external :: zlange | |
991 | 991 | |||
992 | 992 | |||
if (present(status)) status=1 | 993 | 993 | if (present(status)) status=1 | |
994 | 994 | |||
anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | 995 | 995 | anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | |
996 | 996 | |||
allocate(wc_a(d,d)) | 997 | 997 | allocate(wc_a(d,d)) | |
!call zcopy(d*d,a,1,wc_a,1) | 998 | 998 | !call zcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 999 | 999 | wc_a(:,:)=a(:,:) | |
1000 | 1000 | |||
allocate(ipiv(d)) | 1001 | 1001 | allocate(ipiv(d)) | |
call zgetrf(d,d,wc_a,d,ipiv,info) | 1002 | 1002 | call zgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 1003 | 1003 | if (info /= 0) then | |
if (present(status)) status=0 | 1004 | 1004 | if (present(status)) status=0 | |
deallocate(ipiv) | 1005 | 1005 | deallocate(ipiv) | |
deallocate(wc_a) | 1006 | 1006 | deallocate(wc_a) | |
return | 1007 | 1007 | return | |
end if | 1008 | 1008 | end if | |
1009 | 1009 | |||
allocate(work(2*d)) | 1010 | 1010 | allocate(work(2*d)) | |
allocate(rwork(2*d)) | 1011 | 1011 | allocate(rwork(2*d)) | |
call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | 1012 | 1012 | call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | |
if (info /= 0) then | 1013 | 1013 | if (info /= 0) then | |
if (present(status)) status=0 | 1014 | 1014 | if (present(status)) status=0 | |
end if | 1015 | 1015 | end if | |
deallocate(rwork) | 1016 | 1016 | deallocate(rwork) | |
deallocate(work) | 1017 | 1017 | deallocate(work) | |
deallocate(ipiv) | 1018 | 1018 | deallocate(ipiv) | |
deallocate(wc_a) | 1019 | 1019 | deallocate(wc_a) | |
end subroutine | 1020 | 1020 | end subroutine | |
1021 | 1021 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1022 | 1022 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 1023 | 1023 | ! | |
! Valeurs propres/ Vecteurs propre | 1024 | 1024 | ! Valeurs propres/ Vecteurs propre | |
! | 1025 | 1025 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1026 | 1026 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
1027 | 1027 | |||
! August 2009 | 1028 | 1028 | ! August 2009 | |
! William Daniau | 1029 | 1029 | ! William Daniau | |
! Adding sorting of eigenvalues and vectors | 1030 | 1030 | ! Adding sorting of eigenvalues and vectors | |
subroutine fvn_z_sort_eigen(d,v,vec) | 1031 | 1031 | subroutine fvn_z_sort_eigen(d,v,vec) | |
! this routine takes in input : | 1032 | 1032 | ! this routine takes in input : | |
! v : a vector containing unsorted eigenvalues | 1033 | 1033 | ! v : a vector containing unsorted eigenvalues | |
! vec : a matrix where vec(:,j) is the eigenvector corresponding to v(j) | 1034 | 1034 | ! vec : a matrix where vec(:,j) is the eigenvector corresponding to v(j) | |
! | 1035 | 1035 | ! | |
! At the end of subroutine the eigenvalues are sorted by decreasing order of | 1036 | 1036 | ! At the end of subroutine the eigenvalues are sorted by decreasing order of | |
! modulus so as the vectors. | 1037 | 1037 | ! modulus so as the vectors. | |
implicit none | 1038 | 1038 | implicit none | |
integer(kind=ip_kind) :: d,i,j | 1039 | 1039 | integer(kind=ip_kind) :: d,i,j | |
complex(kind=dp_kind),dimension(d) :: v | 1040 | 1040 | complex(kind=dp_kind),dimension(d) :: v | |
complex(kind=dp_kind),dimension(d,d) :: vec | 1041 | 1041 | complex(kind=dp_kind),dimension(d,d) :: vec | |
complex(kind=dp_kind) :: cur_v | 1042 | 1042 | complex(kind=dp_kind) :: cur_v | |
complex(kind=dp_kind), dimension(d) :: cur_vec | 1043 | 1043 | complex(kind=dp_kind), dimension(d) :: cur_vec | |
1044 | 1044 | |||
do i=2,d | 1045 | 1045 | do i=2,d | |
cur_v=v(i) | 1046 | 1046 | cur_v=v(i) | |
cur_vec=vec(:,i) | 1047 | 1047 | cur_vec=vec(:,i) | |
j=i-1 | 1048 | 1048 | j=i-1 | |
do while( (j>=1) .and. (abs(v(j)) < abs(cur_v)) ) | 1049 | 1049 | do while( (j>=1) .and. (abs(v(j)) < abs(cur_v)) ) | |
v(j+1)=v(j) | 1050 | 1050 | v(j+1)=v(j) | |
vec(:,j+1)=vec(:,j) | 1051 | 1051 | vec(:,j+1)=vec(:,j) | |
j=j-1 | 1052 | 1052 | j=j-1 | |
end do | 1053 | 1053 | end do | |
v(j+1)=cur_v | 1054 | 1054 | v(j+1)=cur_v | |
vec(:,j+1)=cur_vec | 1055 | 1055 | vec(:,j+1)=cur_vec | |
end do | 1056 | 1056 | end do | |
1057 | 1057 | |||
end subroutine | 1058 | 1058 | end subroutine | |
1059 | 1059 | |||
subroutine fvn_c_sort_eigen(d,v,vec) | 1060 | 1060 | subroutine fvn_c_sort_eigen(d,v,vec) | |
! this routine takes in input : | 1061 | 1061 | ! this routine takes in input : | |
! v : a vector containing unsorted eigenvalues | 1062 | 1062 | ! v : a vector containing unsorted eigenvalues | |
! vec : a matrix where vec(:,j) is the eigenvector corresponding to v(j) | 1063 | 1063 | ! vec : a matrix where vec(:,j) is the eigenvector corresponding to v(j) | |
! | 1064 | 1064 | ! | |
! At the end of subroutine the eigenvalues are sorted by decreasing order of | 1065 | 1065 | ! At the end of subroutine the eigenvalues are sorted by decreasing order of | |
! modulus so as the vectors. | 1066 | 1066 | ! modulus so as the vectors. | |
implicit none | 1067 | 1067 | implicit none | |
integer(kind=ip_kind) :: d,i,j | 1068 | 1068 | integer(kind=ip_kind) :: d,i,j | |
complex(kind=sp_kind),dimension(d) :: v | 1069 | 1069 | complex(kind=sp_kind),dimension(d) :: v | |
complex(kind=sp_kind),dimension(d,d) :: vec | 1070 | 1070 | complex(kind=sp_kind),dimension(d,d) :: vec | |
complex(kind=sp_kind) :: cur_v | 1071 | 1071 | complex(kind=sp_kind) :: cur_v | |
complex(kind=sp_kind), dimension(d) :: cur_vec | 1072 | 1072 | complex(kind=sp_kind), dimension(d) :: cur_vec | |
1073 | 1073 | |||
do i=2,d | 1074 | 1074 | do i=2,d | |
cur_v=v(i) | 1075 | 1075 | cur_v=v(i) | |
cur_vec=vec(:,i) | 1076 | 1076 | cur_vec=vec(:,i) | |
j=i-1 | 1077 | 1077 | j=i-1 | |
do while( (j>=1) .and. (abs(v(j)) < abs(cur_v)) ) | 1078 | 1078 | do while( (j>=1) .and. (abs(v(j)) < abs(cur_v)) ) | |
v(j+1)=v(j) | 1079 | 1079 | v(j+1)=v(j) | |
vec(:,j+1)=vec(:,j) | 1080 | 1080 | vec(:,j+1)=vec(:,j) | |
j=j-1 | 1081 | 1081 | j=j-1 | |
end do | 1082 | 1082 | end do | |
v(j+1)=cur_v | 1083 | 1083 | v(j+1)=cur_v | |
vec(:,j+1)=cur_vec | 1084 | 1084 | vec(:,j+1)=cur_vec | |
end do | 1085 | 1085 | end do | |
1086 | 1086 | |||
end subroutine | 1087 | 1087 | end subroutine | |
1088 | 1088 | |||
subroutine fvn_s_matev(d,a,evala,eveca,status,sortval) | 1089 | 1089 | subroutine fvn_s_matev(d,a,evala,eveca,status,sortval) | |
! | 1090 | 1090 | ! | |
! integer(kind=ip_kind) d (in) : matrice rank | 1091 | 1091 | ! integer(kind=ip_kind) d (in) : matrice rank | |
! real(kind=sp_kind) a(d,d) (in) : The Matrix | 1092 | 1092 | ! real(kind=sp_kind) a(d,d) (in) : The Matrix | |
! complex(kind=sp_kind) evala(d) (out) : eigenvalues | 1093 | 1093 | ! complex(kind=sp_kind) evala(d) (out) : eigenvalues | |
! complex(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1094 | 1094 | ! complex(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer(kind=ip_kind) (out) : status =0 if something went wrong | 1095 | 1095 | ! integer(kind=ip_kind) (out) : status =0 if something went wrong | |
! | 1096 | 1096 | ! | |
! interfacing Lapack routine SGEEV | 1097 | 1097 | ! interfacing Lapack routine SGEEV | |
1098 | ! 2020 11 03 : SGEEVX with BALANC='N' | |||
implicit none | 1098 | 1099 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 1099 | 1100 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=sp_kind), intent(in) :: a(d,d) | 1100 | 1101 | real(kind=sp_kind), intent(in) :: a(d,d) | |
complex(kind=sp_kind), intent(out) :: evala(d) | 1101 | 1102 | complex(kind=sp_kind), intent(out) :: evala(d) | |
complex(kind=sp_kind), intent(out) :: eveca(d,d) | 1102 | 1103 | complex(kind=sp_kind), intent(out) :: eveca(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 1103 | 1104 | integer(kind=ip_kind), intent(out), optional :: status | |
logical(kind=ip_kind), intent(in), optional :: sortval | 1104 | 1105 | logical(kind=ip_kind), intent(in), optional :: sortval | |
1105 | 1106 | |||
real(kind=sp_kind), allocatable :: wc_a(:,:) ! a working copy of a | 1106 | 1107 | real(kind=sp_kind), allocatable :: wc_a(:,:) ! a working copy of a | |
integer(kind=ip_kind) :: info | 1107 | 1108 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 1108 | 1109 | integer(kind=ip_kind) :: lwork | |
real(kind=sp_kind), allocatable :: wr(:),wi(:) | 1109 | 1110 | real(kind=sp_kind), allocatable :: wr(:),wi(:) | |
real(kind=sp_kind) :: vl ! unused but necessary for the call | 1110 | 1111 | real(kind=sp_kind) :: vl ! unused but necessary for the call | |
real(kind=sp_kind), allocatable :: vr(:,:) | 1111 | 1112 | real(kind=sp_kind), allocatable :: vr(:,:) | |
real(kind=sp_kind), allocatable :: work(:) | 1112 | 1113 | real(kind=sp_kind), allocatable :: work(:) | |
real(kind=sp_kind) :: twork(1) | 1113 | 1114 | real(kind=sp_kind) :: twork(1) | |
integer(kind=ip_kind) i | 1114 | 1115 | integer(kind=ip_kind) i | |
integer(kind=ip_kind) j | 1115 | 1116 | integer(kind=ip_kind) j | |
1116 | 1117 | |||
1118 | integer(kind=ip_kind) :: ilo,ihi, iwork | |||
1119 | real(kind=sp_kind), allocatable, dimension(:) :: scal, rconde, rcondv | |||
1120 | real(kind=sp_kind) :: abnrm | |||
1121 | ||||
if (present(status)) status=1 | 1117 | 1122 | if (present(status)) status=1 | |
1118 | 1123 | |||
! making a working copy of a | 1119 | 1124 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1120 | 1125 | allocate(wc_a(d,d)) | |
!call scopy(d*d,a,1,wc_a,1) | 1121 | 1126 | !call scopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1122 | 1127 | wc_a(:,:)=a(:,:) | |
1123 | 1128 | |||
allocate(wr(d)) | 1124 | 1129 | allocate(wr(d)) | |
allocate(wi(d)) | 1125 | 1130 | allocate(wi(d)) | |
allocate(vr(d,d)) | 1126 | 1131 | allocate(vr(d,d)) | |
1132 | allocate(scal(d),rconde(d),rcondv(d)) | |||
! query optimal work size | 1127 | 1133 | ! query optimal work size | |
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | 1128 | 1134 | ! call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | |
1135 | call sgeevx('N','N','V','N',d,wc_a,d,wr,wi,vl,1,vr,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,twork,-1,IWORK,info) | |||
lwork=int(twork(1)) | 1129 | 1136 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1130 | 1137 | allocate(work(lwork)) | |
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | 1131 | 1138 | ! call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | |
1139 | call sgeevx('N','N','V','N',d,wc_a,d,wr,wi,vl,1,vr,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,work,lwork,IWORK,info) | |||
1132 | 1140 | |||
1141 | ||||
if (info /= 0) then | 1133 | 1142 | if (info /= 0) then | |
if (present(status)) status=0 | 1134 | 1143 | if (present(status)) status=0 | |
deallocate(work) | 1135 | 1144 | deallocate(work) | |
deallocate(vr) | 1136 | 1145 | deallocate(vr) | |
deallocate(wi) | 1137 | 1146 | deallocate(wi) | |
deallocate(wr) | 1138 | 1147 | deallocate(wr) | |
deallocate(wc_a) | 1139 | 1148 | deallocate(wc_a) | |
1149 | deallocate(scal,rconde,rcondv) | |||
return | 1140 | 1150 | return | |
end if | 1141 | 1151 | end if | |
1142 | 1152 | |||
! now fill in the results | 1143 | 1153 | ! now fill in the results | |
i=1 | 1144 | 1154 | i=1 | |
do while(i<=d) | 1145 | 1155 | do while(i<=d) | |
evala(i)=cmplx(wr(i),wi(i)) | 1146 | 1156 | evala(i)=cmplx(wr(i),wi(i)) | |
if (wi(i) == 0.) then ! eigenvalue is real | 1147 | 1157 | if (wi(i) == 0.) then ! eigenvalue is real | |
eveca(:,i)=cmplx(vr(:,i),0.) | 1148 | 1158 | eveca(:,i)=cmplx(vr(:,i),0.) | |
else ! eigenvalue is complex | 1149 | 1159 | else ! eigenvalue is complex | |
evala(i+1)=cmplx(wr(i+1),wi(i+1)) | 1150 | 1160 | evala(i+1)=cmplx(wr(i+1),wi(i+1)) | |
eveca(:,i)=cmplx(vr(:,i),vr(:,i+1)) | 1151 | 1161 | eveca(:,i)=cmplx(vr(:,i),vr(:,i+1)) | |
eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1)) | 1152 | 1162 | eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1)) | |
i=i+1 | 1153 | 1163 | i=i+1 | |
end if | 1154 | 1164 | end if | |
i=i+1 | 1155 | 1165 | i=i+1 | |
enddo | 1156 | 1166 | enddo | |
deallocate(work) | 1157 | 1167 | deallocate(work) | |
deallocate(vr) | 1158 | 1168 | deallocate(vr) | |
deallocate(wi) | 1159 | 1169 | deallocate(wi) | |
deallocate(wr) | 1160 | 1170 | deallocate(wr) | |
deallocate(wc_a) | 1161 | 1171 | deallocate(wc_a) | |
1172 | deallocate(scal,rconde,rcondv) | |||
1162 | 1173 | |||
! sorting | 1163 | 1174 | ! sorting | |
if (present(sortval) .and. sortval) then | 1164 | 1175 | if (present(sortval) .and. sortval) then | |
call fvn_c_sort_eigen(d,evala,eveca) | 1165 | 1176 | call fvn_c_sort_eigen(d,evala,eveca) | |
end if | 1166 | 1177 | end if | |
1167 | 1178 | |||
end subroutine | 1168 | 1179 | end subroutine | |
1169 | 1180 | |||
subroutine fvn_d_matev(d,a,evala,eveca,status,sortval) | 1170 | 1181 | subroutine fvn_d_matev(d,a,evala,eveca,status,sortval) | |
! | 1171 | 1182 | ! | |
! integer(kind=ip_kind) d (in) : matrice rank | 1172 | 1183 | ! integer(kind=ip_kind) d (in) : matrice rank | |
! real(kind=dp_kind) a(d,d) (in) : The Matrix | 1173 | 1184 | ! real(kind=dp_kind) a(d,d) (in) : The Matrix | |
! complex(kind=dp_kind)(kind=sp_kind) evala(d) (out) : eigenvalues | 1174 | 1185 | ! complex(kind=dp_kind)(kind=sp_kind) evala(d) (out) : eigenvalues | |
! complex(kind=dp_kind)(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1175 | 1186 | ! complex(kind=dp_kind)(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer(kind=ip_kind) (out) : status =0 if something went wrong | 1176 | 1187 | ! integer(kind=ip_kind) (out) : status =0 if something went wrong | |
! | 1177 | 1188 | ! | |
! interfacing Lapack routine DGEEV | 1178 | 1189 | ! interfacing Lapack routine DGEEV | |
1190 | ! 2020 11 03 : DGEEVX with BALANC='N' | |||
implicit none | 1179 | 1191 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 1180 | 1192 | integer(kind=ip_kind), intent(in) :: d | |
real(kind=dp_kind), intent(in) :: a(d,d) | 1181 | 1193 | real(kind=dp_kind), intent(in) :: a(d,d) | |
complex(kind=dp_kind), intent(out) :: evala(d) | 1182 | 1194 | complex(kind=dp_kind), intent(out) :: evala(d) | |
complex(kind=dp_kind), intent(out) :: eveca(d,d) | 1183 | 1195 | complex(kind=dp_kind), intent(out) :: eveca(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 1184 | 1196 | integer(kind=ip_kind), intent(out), optional :: status | |
logical(kind=ip_kind), intent(in), optional :: sortval | 1185 | 1197 | logical(kind=ip_kind), intent(in), optional :: sortval | |
1186 | 1198 | |||
real(kind=dp_kind), allocatable :: wc_a(:,:) ! a working copy of a | 1187 | 1199 | real(kind=dp_kind), allocatable :: wc_a(:,:) ! a working copy of a | |
integer(kind=ip_kind) :: info | 1188 | 1200 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 1189 | 1201 | integer(kind=ip_kind) :: lwork | |
real(kind=dp_kind), allocatable :: wr(:),wi(:) | 1190 | 1202 | real(kind=dp_kind), allocatable :: wr(:),wi(:) | |
real(kind=dp_kind) :: vl ! unused but necessary for the call | 1191 | 1203 | real(kind=dp_kind) :: vl ! unused but necessary for the call | |
real(kind=dp_kind), allocatable :: vr(:,:) | 1192 | 1204 | real(kind=dp_kind), allocatable :: vr(:,:) | |
real(kind=dp_kind), allocatable :: work(:) | 1193 | 1205 | real(kind=dp_kind), allocatable :: work(:) | |
real(kind=dp_kind) :: twork(1) | 1194 | 1206 | real(kind=dp_kind) :: twork(1) | |
integer(kind=ip_kind) i | 1195 | 1207 | integer(kind=ip_kind) i | |
integer(kind=ip_kind) j | 1196 | 1208 | integer(kind=ip_kind) j | |
1197 | 1209 | |||
1210 | integer(kind=ip_kind) :: ilo,ihi, iwork | |||
1211 | real(kind=dp_kind), allocatable, dimension(:) :: scal, rconde, rcondv | |||
1212 | real(kind=dp_kind) :: abnrm | |||
1213 | ||||
if (present(status)) status=1 | 1198 | 1214 | if (present(status)) status=1 | |
1199 | 1215 | |||
! making a working copy of a | 1200 | 1216 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1201 | 1217 | allocate(wc_a(d,d)) | |
!call dcopy(d*d,a,1,wc_a,1) | 1202 | 1218 | !call dcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1203 | 1219 | wc_a(:,:)=a(:,:) | |
1204 | 1220 | |||
allocate(wr(d)) | 1205 | 1221 | allocate(wr(d)) | |
allocate(wi(d)) | 1206 | 1222 | allocate(wi(d)) | |
allocate(vr(d,d)) | 1207 | 1223 | allocate(vr(d,d)) | |
1224 | allocate(scal(d),rconde(d),rcondv(d)) | |||
! query optimal work size | 1208 | 1225 | ! query optimal work size | |
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | 1209 | 1226 | ! call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | |
1227 | call dgeevx('N','N','V','N',d,wc_a,d,wr,wi,vl,1,vr,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,twork,-1,IWORK,info) | |||
lwork=int(twork(1)) | 1210 | 1228 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1211 | 1229 | allocate(work(lwork)) | |
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | 1212 | 1230 | ! call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | |
1231 | call dgeevx('N','N','V','N',d,wc_a,d,wr,wi,vl,1,vr,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,work,lwork,IWORK,info) | |||
1213 | 1232 | |||
if (info /= 0) then | 1214 | 1233 | if (info /= 0) then | |
if (present(status)) status=0 | 1215 | 1234 | if (present(status)) status=0 | |
deallocate(work) | 1216 | 1235 | deallocate(work) | |
deallocate(vr) | 1217 | 1236 | deallocate(vr) | |
deallocate(wi) | 1218 | 1237 | deallocate(wi) | |
deallocate(wr) | 1219 | 1238 | deallocate(wr) | |
deallocate(wc_a) | 1220 | 1239 | deallocate(wc_a) | |
1240 | deallocate(scal,rconde,rcondv) | |||
return | 1221 | 1241 | return | |
end if | 1222 | 1242 | end if | |
1223 | 1243 | |||
! now fill in the results | 1224 | 1244 | ! now fill in the results | |
i=1 | 1225 | 1245 | i=1 | |
do while(i<=d) | 1226 | 1246 | do while(i<=d) | |
evala(i)=cmplx(wr(i),wi(i),dp_kind) | 1227 | 1247 | evala(i)=cmplx(wr(i),wi(i),dp_kind) | |
if (wi(i) == 0.) then ! eigenvalue is real | 1228 | 1248 | if (wi(i) == 0.) then ! eigenvalue is real | |
eveca(:,i)=cmplx(vr(:,i),0._dp_kind,dp_kind) | 1229 | 1249 | eveca(:,i)=cmplx(vr(:,i),0._dp_kind,dp_kind) | |
else ! eigenvalue is complex | 1230 | 1250 | else ! eigenvalue is complex | |
evala(i+1)=cmplx(wr(i+1),wi(i+1),dp_kind) | 1231 | 1251 | evala(i+1)=cmplx(wr(i+1),wi(i+1),dp_kind) | |
eveca(:,i)=cmplx(vr(:,i),vr(:,i+1),dp_kind) | 1232 | 1252 | eveca(:,i)=cmplx(vr(:,i),vr(:,i+1),dp_kind) | |
eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1),dp_kind) | 1233 | 1253 | eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1),dp_kind) | |
i=i+1 | 1234 | 1254 | i=i+1 | |
end if | 1235 | 1255 | end if | |
i=i+1 | 1236 | 1256 | i=i+1 | |
enddo | 1237 | 1257 | enddo | |
1238 | 1258 | |||
deallocate(work) | 1239 | 1259 | deallocate(work) | |
deallocate(vr) | 1240 | 1260 | deallocate(vr) | |
deallocate(wi) | 1241 | 1261 | deallocate(wi) | |
deallocate(wr) | 1242 | 1262 | deallocate(wr) | |
deallocate(wc_a) | 1243 | 1263 | deallocate(wc_a) | |
1264 | deallocate(scal,rconde,rcondv) | |||
1244 | 1265 | |||
! sorting | 1245 | 1266 | ! sorting | |
if (present(sortval) .and. sortval) then | 1246 | 1267 | if (present(sortval) .and. sortval) then | |
call fvn_z_sort_eigen(d,evala,eveca) | 1247 | 1268 | call fvn_z_sort_eigen(d,evala,eveca) | |
end if | 1248 | 1269 | end if | |
1249 | 1270 | |||
end subroutine | 1250 | 1271 | end subroutine | |
1251 | 1272 | |||
subroutine fvn_c_matev(d,a,evala,eveca,status,sortval) | 1252 | 1273 | subroutine fvn_c_matev(d,a,evala,eveca,status,sortval) | |
! | 1253 | 1274 | ! | |
! integer(kind=ip_kind) d (in) : matrice rank | 1254 | 1275 | ! integer(kind=ip_kind) d (in) : matrice rank | |
! complex(kind=sp_kind) a(d,d) (in) : The Matrix | 1255 | 1276 | ! complex(kind=sp_kind) a(d,d) (in) : The Matrix | |
! complex(kind=sp_kind) evala(d) (out) : eigenvalues | 1256 | 1277 | ! complex(kind=sp_kind) evala(d) (out) : eigenvalues | |
! complex(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1257 | 1278 | ! complex(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer(kind=ip_kind) (out) : status =0 if something went wrong | 1258 | 1279 | ! integer(kind=ip_kind) (out) : status =0 if something went wrong | |
! | 1259 | 1280 | ! | |
! interfacing Lapack routine CGEEV | 1260 | 1281 | ! interfacing Lapack routine CGEEV | |
1282 | ! 2020 11 03 : CGEEVX with BALANC='N' | |||
implicit none | 1261 | 1283 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 1262 | 1284 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=sp_kind), intent(in) :: a(d,d) | 1263 | 1285 | complex(kind=sp_kind), intent(in) :: a(d,d) | |
complex(kind=sp_kind), intent(out) :: evala(d) | 1264 | 1286 | complex(kind=sp_kind), intent(out) :: evala(d) | |
complex(kind=sp_kind), intent(out) :: eveca(d,d) | 1265 | 1287 | complex(kind=sp_kind), intent(out) :: eveca(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 1266 | 1288 | integer(kind=ip_kind), intent(out), optional :: status | |
logical(kind=ip_kind), intent(in), optional :: sortval | 1267 | 1289 | logical(kind=ip_kind), intent(in), optional :: sortval | |
1268 | 1290 | |||
complex(kind=sp_kind), allocatable :: wc_a(:,:) ! a working copy of a | 1269 | 1291 | complex(kind=sp_kind), allocatable :: wc_a(:,:) ! a working copy of a | |
integer(kind=ip_kind) :: info | 1270 | 1292 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 1271 | 1293 | integer(kind=ip_kind) :: lwork | |
complex(kind=sp_kind), allocatable :: work(:) | 1272 | 1294 | complex(kind=sp_kind), allocatable :: work(:) | |
complex(kind=sp_kind) :: twork(1) | 1273 | 1295 | complex(kind=sp_kind) :: twork(1) | |
real(kind=sp_kind), allocatable :: rwork(:) | 1274 | 1296 | real(kind=sp_kind), allocatable :: rwork(:) | |
complex(kind=sp_kind) :: vl ! unused but necessary for the call | 1275 | 1297 | complex(kind=sp_kind) :: vl ! unused but necessary for the call | |
1276 | 1298 | |||
1299 | integer(kind=ip_kind) :: ilo,ihi | |||
1300 | real(kind=sp_kind), allocatable, dimension(:) :: scal, rconde, rcondv | |||
1301 | real(kind=sp_kind) :: abnrm | |||
1302 | ||||
if (present(status)) status=1 | 1277 | 1303 | if (present(status)) status=1 | |
1278 | 1304 | |||
! making a working copy of a | 1279 | 1305 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1280 | 1306 | allocate(wc_a(d,d)) | |
!call ccopy(d*d,a,1,wc_a,1) | 1281 | 1307 | !call ccopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1282 | 1308 | wc_a(:,:)=a(:,:) | |
1283 | 1309 | |||
! rwork must be allocated before query | 1284 | 1310 | ! rwork must be allocated before query | |
allocate(rwork(2*d)) | 1285 | 1311 | allocate(rwork(2*d)) | |
1312 | allocate(scal(d),rconde(d),rcondv(d)) | |||
! query optimal work size | 1286 | 1313 | ! query optimal work size | |
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | 1287 | 1314 | ! call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | |
1315 | call cgeevx('N','N','V','N',d,wc_a,d,evala,vl,1,eveca,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,twork,-1,rwork,info) | |||
lwork=int(twork(1)) | 1288 | 1316 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1289 | 1317 | allocate(work(lwork)) | |
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | 1290 | 1318 | ! call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | |
1319 | call cgeevx('N','N','V','N',d,wc_a,d,evala,vl,1,eveca,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,work,lwork,rwork,info) | |||
1291 | 1320 | |||
if (info /= 0) then | 1292 | 1321 | if (info /= 0) then | |
if (present(status)) status=0 | 1293 | 1322 | if (present(status)) status=0 | |
end if | 1294 | 1323 | end if | |
deallocate(rwork) | 1295 | 1324 | deallocate(rwork) | |
deallocate(work) | 1296 | 1325 | deallocate(work) | |
deallocate(wc_a) | 1297 | 1326 | deallocate(wc_a) | |
1327 | deallocate(scal,rconde,rcondv) | |||
1298 | 1328 | |||
! sorting | 1299 | 1329 | ! sorting | |
if (present(sortval) .and. sortval) then | 1300 | 1330 | if (present(sortval) .and. sortval) then | |
call fvn_c_sort_eigen(d,evala,eveca) | 1301 | 1331 | call fvn_c_sort_eigen(d,evala,eveca) | |
end if | 1302 | 1332 | end if | |
1303 | 1333 | |||
end subroutine | 1304 | 1334 | end subroutine | |
1305 | 1335 | |||
subroutine fvn_z_matev(d,a,evala,eveca,status,sortval) | 1306 | 1336 | subroutine fvn_z_matev(d,a,evala,eveca,status,sortval) | |
! | 1307 | 1337 | ! | |
! integer(kind=ip_kind) d (in) : matrice rank | 1308 | 1338 | ! integer(kind=ip_kind) d (in) : matrice rank | |
! complex(kind=dp_kind)(kind=sp_kind) a(d,d) (in) : The Matrix | 1309 | 1339 | ! complex(kind=dp_kind)(kind=sp_kind) a(d,d) (in) : The Matrix | |
! complex(kind=dp_kind)(kind=sp_kind) evala(d) (out) : eigenvalues | 1310 | 1340 | ! complex(kind=dp_kind)(kind=sp_kind) evala(d) (out) : eigenvalues | |
! complex(kind=dp_kind)(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1311 | 1341 | ! complex(kind=dp_kind)(kind=sp_kind) eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer(kind=ip_kind) (out) : status =0 if something went wrong | 1312 | 1342 | ! integer(kind=ip_kind) (out) : status =0 if something went wrong | |
! | 1313 | 1343 | ! | |
! interfacing Lapack routine ZGEEV | 1314 | 1344 | ! interfacing Lapack routine ZGEEV | |
1345 | ! 2020 11 03 : ZGEEVX with BALANC='N' | |||
implicit none | 1315 | 1346 | implicit none | |
integer(kind=ip_kind), intent(in) :: d | 1316 | 1347 | integer(kind=ip_kind), intent(in) :: d | |
complex(kind=dp_kind), intent(in) :: a(d,d) | 1317 | 1348 | complex(kind=dp_kind), intent(in) :: a(d,d) | |
complex(kind=dp_kind), intent(out) :: evala(d) | 1318 | 1349 | complex(kind=dp_kind), intent(out) :: evala(d) | |
complex(kind=dp_kind), intent(out) :: eveca(d,d) | 1319 | 1350 | complex(kind=dp_kind), intent(out) :: eveca(d,d) | |
integer(kind=ip_kind), intent(out), optional :: status | 1320 | 1351 | integer(kind=ip_kind), intent(out), optional :: status | |
logical(kind=ip_kind), intent(in), optional :: sortval | 1321 | 1352 | logical(kind=ip_kind), intent(in), optional :: sortval | |
1322 | 1353 | |||
complex(kind=dp_kind), allocatable :: wc_a(:,:) ! a working copy of a | 1323 | 1354 | complex(kind=dp_kind), allocatable :: wc_a(:,:) ! a working copy of a | |
integer(kind=ip_kind) :: info | 1324 | 1355 | integer(kind=ip_kind) :: info | |
integer(kind=ip_kind) :: lwork | 1325 | 1356 | integer(kind=ip_kind) :: lwork | |
complex(kind=dp_kind), allocatable :: work(:) | 1326 | 1357 | complex(kind=dp_kind), allocatable :: work(:) | |
complex(kind=dp_kind) :: twork(1) | 1327 | 1358 | complex(kind=dp_kind) :: twork(1) | |
real(kind=dp_kind), allocatable :: rwork(:) | 1328 | 1359 | real(kind=dp_kind), allocatable :: rwork(:) | |
complex(kind=dp_kind) :: vl ! unused but necessary for the call | 1329 | 1360 | complex(kind=dp_kind) :: vl ! unused but necessary for the call | |
1330 | 1361 | |||
1362 | integer(kind=ip_kind) :: ilo,ihi | |||
1363 | real(kind=dp_kind), allocatable, dimension(:) :: scal, rconde, rcondv | |||
1364 | real(kind=dp_kind) :: abnrm | |||
1365 | ||||
1366 | ||||
if (present(status)) status=1 | 1331 | 1367 | if (present(status)) status=1 | |
1332 | 1368 | |||
! making a working copy of a | 1333 | 1369 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1334 | 1370 | allocate(wc_a(d,d)) | |
!call zcopy(d*d,a,1,wc_a,1) | 1335 | 1371 | !call zcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1336 | 1372 | wc_a(:,:)=a(:,:) | |
1337 | 1373 | |||
! rwork must be allocated before query | 1338 | 1374 | ! rwork must be allocated before query | |
allocate(rwork(2*d)) | 1339 | 1375 | allocate(rwork(2*d)) | |
1376 | allocate(scal(d),rconde(d),rcondv(d)) | |||
! query optimal work size | 1340 | 1377 | ! query optimal work size | |
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | 1341 | 1378 | ! call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | |
1379 | call zgeevx('N','N','V','N',d,wc_a,d,evala,vl,1,eveca,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,twork,-1,rwork,info) | |||
lwork=int(twork(1)) | 1342 | 1380 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1343 | 1381 | allocate(work(lwork)) | |
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | 1344 | 1382 | ! call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | |
1383 | call zgeevx('N','N','V','N',d,wc_a,d,evala,vl,1,eveca,d,ILO,IHI,SCAL,ABNRM,RCONDE,RCONDV,work,lwork,rwork,info) | |||
1345 | 1384 | |||
if (info /= 0) then | 1346 | 1385 | if (info /= 0) then | |
if (present(status)) status=0 | 1347 | 1386 | if (present(status)) status=0 | |
end if | 1348 | 1387 | end if | |
deallocate(rwork) | 1349 | 1388 | deallocate(rwork) | |
deallocate(work) | 1350 | 1389 | deallocate(work) | |
deallocate(wc_a) | 1351 | 1390 | deallocate(wc_a) | |
1391 | deallocate(scal,rconde,rcondv) | |||
1352 | 1392 | |||
! sorting | 1353 | 1393 | ! sorting | |
if (present(sortval) .and. sortval) then | 1354 | 1394 | if (present(sortval) .and. sortval) then | |
call fvn_z_sort_eigen(d,evala,eveca) | 1355 | 1395 | call fvn_z_sort_eigen(d,evala,eveca) | |
end if | 1356 | 1396 | end if | |
end subroutine | 1357 | 1397 | end subroutine | |
1358 | 1398 | |||
1359 | 1399 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1360 | 1400 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 1361 | 1401 | ! | |
! Least square problem | 1362 | 1402 | ! Least square problem | |
! | 1363 | 1403 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1364 | 1404 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 1365 | 1405 | ! | |
! | 1366 | 1406 | ! | |
1367 | 1407 | |||
1368 | 1408 | |||
1369 | 1409 | |||
1370 | 1410 | |||
subroutine fvn_d_lspoly(np,x,y,deg,coeff,status) | 1371 | 1411 | subroutine fvn_d_lspoly(np,x,y,deg,coeff,status) | |
! | 1372 | 1412 | ! | |
! Least square polynomial fitting | 1373 | 1413 | ! Least square polynomial fitting | |
! | 1374 | 1414 | ! | |
! Find the coefficients of the least square polynomial of a given degree | 1375 | 1415 | ! Find the coefficients of the least square polynomial of a given degree | |
! for a set of coordinates. | 1376 | 1416 | ! for a set of coordinates. | |
! | 1377 | 1417 | ! | |
! The degree must be lower than the number of points | 1378 | 1418 | ! The degree must be lower than the number of points | |
! | 1379 | 1419 | ! | |
! np (in) : number of points | 1380 | 1420 | ! np (in) : number of points | |
! x(np) (in) : x data | 1381 | 1421 | ! x(np) (in) : x data | |
! y(np) (in) : y data | 1382 | 1422 | ! y(np) (in) : y data | |
! deg (in) : polynomial's degree | 1383 | 1423 | ! deg (in) : polynomial's degree | |
! coeff(deg+1) (out) : polynomial coefficients | 1384 | 1424 | ! coeff(deg+1) (out) : polynomial coefficients | |
! status (out) : =0 if a problem occurs | 1385 | 1425 | ! status (out) : =0 if a problem occurs | |
! | 1386 | 1426 | ! | |
implicit none | 1387 | 1427 | implicit none |