Commit 42627b85e3786e526a4c2c75e81ec4bd80890a42
1 parent
fdbb9bb0a5
Exists in
master
and in
3 other branches
git-svn-id: https://lxsd.femto-st.fr/svn/fvn@48 b657c933-2333-4658-acf2-d3c7c2708721
Showing 1 changed file with 16 additions and 8 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(4), dimension(:,:),intent(in) :: a,b | 105 | 105 | real(4), dimension(:,:),intent(in) :: a,b | |
real(4), dimension(size(a,1),size(b,2)) :: fvn_op_s_matmul | 106 | 106 | real(4), 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(8), dimension(:,:),intent(in) :: a,b | 111 | 111 | real(8), dimension(:,:),intent(in) :: a,b | |
real(8), dimension(size(a,1),size(b,2)) :: fvn_op_d_matmul | 112 | 112 | real(8), 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(4), dimension(:,:),intent(in) :: a,b | 117 | 117 | complex(4), dimension(:,:),intent(in) :: a,b | |
complex(4), dimension(size(a,1),size(b,2)) :: fvn_op_c_matmul | 118 | 118 | complex(4), 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(8), dimension(:,:), intent(in) :: a,b | 123 | 123 | complex(8), dimension(:,:), intent(in) :: a,b | |
complex(8), dimension(size(a,1),size(b,2)) :: fvn_op_z_matmul | 124 | 124 | complex(8), 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(4), dimension(:,:), intent(in) :: a,b | 133 | 133 | real(4), dimension(:,:), intent(in) :: a,b | |
real(4), dimension(size(a,2),size(b,2)) :: fvn_op_s_tx | 134 | 134 | real(4), 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(8), dimension(:,:), intent(in) :: a,b | 139 | 139 | real(8), dimension(:,:), intent(in) :: a,b | |
real(8), dimension(size(a,2),size(b,2)) :: fvn_op_d_tx | 140 | 140 | real(8), 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(4), dimension(:,:), intent(in) :: a,b | 145 | 145 | complex(4), dimension(:,:), intent(in) :: a,b | |
complex(4), dimension(size(a,2),size(b,2)) :: fvn_op_c_tx | 146 | 146 | complex(4), 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(8), dimension(:,:), intent(in) :: a,b | 151 | 151 | complex(8), dimension(:,:), intent(in) :: a,b | |
complex(8), dimension(size(a,2),size(b,2)) :: fvn_op_z_tx | 152 | 152 | complex(8), 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(4), dimension(:,:), intent(in) :: a,b | 162 | 162 | real(4), dimension(:,:), intent(in) :: a,b | |
real(4), dimension(size(a,1),size(b,1)) :: fvn_op_s_xt | 163 | 163 | real(4), 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(8), dimension(:,:), intent(in) :: a,b | 168 | 168 | real(8), dimension(:,:), intent(in) :: a,b | |
real(8), dimension(size(a,1),size(b,1)) :: fvn_op_d_xt | 169 | 169 | real(8), 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(4), dimension(:,:), intent(in) :: a,b | 174 | 174 | complex(4), dimension(:,:), intent(in) :: a,b | |
complex(4), dimension(size(a,1),size(b,1)) :: fvn_op_c_xt | 175 | 175 | complex(4), 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(8), dimension(:,:), intent(in) :: a,b | 180 | 180 | complex(8), dimension(:,:), intent(in) :: a,b | |
complex(8), dimension(size(a,1),size(b,1)) :: fvn_op_z_xt | 181 | 181 | complex(8), 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(4),dimension(:,:),intent(in) :: a | 190 | 190 | real(4),dimension(:,:),intent(in) :: a | |
real(4),dimension(size(a,2),size(a,1)) :: fvn_op_s_transpose | 191 | 191 | real(4),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(8),dimension(:,:),intent(in) :: a | 196 | 196 | real(8),dimension(:,:),intent(in) :: a | |
real(8),dimension(size(a,2),size(a,1)) :: fvn_op_d_transpose | 197 | 197 | real(8),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(4),dimension(:,:),intent(in) :: a | 202 | 202 | complex(4),dimension(:,:),intent(in) :: a | |
complex(4),dimension(size(a,2),size(a,1)) :: fvn_op_c_transpose | 203 | 203 | complex(4),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(8),dimension(:,:),intent(in) :: a | 208 | 208 | complex(8),dimension(:,:),intent(in) :: a | |
complex(8),dimension(size(a,2),size(a,1)) :: fvn_op_z_transpose | 209 | 209 | complex(8),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 | ! | |
216 | ! It seems that there's a problem with automatic arrays with gfortran | |||
217 | ! in some circumstances. To allow compilation with gfortran we use here a temporary array | |||
218 | ! for the call. Without that there's a warning at compile time and a segmentation fault | |||
219 | ! during execution. This is odd as we double memory use. | |||
function fvn_op_s_matinv(a) | 216 | 220 | function fvn_op_s_matinv(a) | |
implicit none | 217 | 221 | implicit none | |
real(4),dimension(:,:),intent(in) :: a | 218 | 222 | real(4),dimension(:,:),intent(in) :: a | |
real(4),dimension(size(a,1),size(a,1)) :: fvn_op_s_matinv | 219 | 223 | real(4),dimension(size(a,1),size(a,1)) :: fvn_op_s_matinv,tmp_array | |
call fvn_s_matinv(size(a,1),a,fvn_op_s_matinv,fvn_status) | 220 | 224 | call fvn_s_matinv(size(a,1),a,tmp_array,fvn_status) | |
225 | fvn_op_s_matinv=tmp_array | |||
end function | 221 | 226 | end function | |
function fvn_op_d_matinv(a) | 222 | 227 | function fvn_op_d_matinv(a) | |
implicit none | 223 | 228 | implicit none | |
real(8),dimension(:,:),intent(in) :: a | 224 | 229 | real(8),dimension(:,:),intent(in) :: a | |
real(8),dimension(size(a,1),size(a,1)) :: fvn_op_d_matinv | 225 | 230 | real(8),dimension(size(a,1),size(a,1)) :: fvn_op_d_matinv,tmp_array | |
call fvn_d_matinv(size(a,1),a,fvn_op_d_matinv,fvn_status) | 226 | 231 | call fvn_d_matinv(size(a,1),a,tmp_array,fvn_status) | |
232 | fvn_op_d_matinv=tmp_array | |||
end function | 227 | 233 | end function | |
function fvn_op_c_matinv(a) | 228 | 234 | function fvn_op_c_matinv(a) | |
implicit none | 229 | 235 | implicit none | |
complex(4),dimension(:,:),intent(in) :: a | 230 | 236 | complex(4),dimension(:,:),intent(in) :: a | |
complex(4),dimension(size(a,1),size(a,1)) :: fvn_op_c_matinv | 231 | 237 | complex(4),dimension(size(a,1),size(a,1)) :: fvn_op_c_matinv,tmp_array | |
call fvn_c_matinv(size(a,1),a,fvn_op_c_matinv,fvn_status) | 232 | 238 | call fvn_c_matinv(size(a,1),a,tmp_array,fvn_status) | |
239 | fvn_op_c_matinv=tmp_array | |||
end function | 233 | 240 | end function | |
function fvn_op_z_matinv(a) | 234 | 241 | function fvn_op_z_matinv(a) | |
implicit none | 235 | 242 | implicit none | |
complex(8),dimension(:,:),intent(in) :: a | 236 | 243 | complex(8),dimension(:,:),intent(in) :: a | |
complex(8),dimension(size(a,1),size(a,1)) :: fvn_op_z_matinv | 237 | 244 | complex(8),dimension(size(a,1),size(a,1)) :: fvn_op_z_matinv,tmp_array | |
call fvn_z_matinv(size(a,1),a,fvn_op_z_matinv,fvn_status) | 238 | 245 | call fvn_z_matinv(size(a,1),a,tmp_array,fvn_status) | |
246 | fvn_op_z_matinv=tmp_array | |||
end function | 239 | 247 | end function | |
240 | 248 | |||
! | 241 | 249 | ! | |
! .ix. | 242 | 250 | ! .ix. | |
! | 243 | 251 | ! | |
function fvn_op_s_ix(a,b) | 244 | 252 | function fvn_op_s_ix(a,b) | |
implicit none | 245 | 253 | implicit none | |
real(4), dimension(:,:), intent(in) :: a,b | 246 | 254 | real(4), dimension(:,:), intent(in) :: a,b | |
real(4), dimension(size(a,1),size(b,2)) :: fvn_op_s_ix | 247 | 255 | real(4), dimension(size(a,1),size(b,2)) :: fvn_op_s_ix | |
fvn_op_s_ix=matmul(fvn_op_s_matinv(a),b) | 248 | 256 | fvn_op_s_ix=matmul(fvn_op_s_matinv(a),b) | |
end function | 249 | 257 | end function | |
function fvn_op_d_ix(a,b) | 250 | 258 | function fvn_op_d_ix(a,b) | |
implicit none | 251 | 259 | implicit none | |
real(8), dimension(:,:), intent(in) :: a,b | 252 | 260 | real(8), dimension(:,:), intent(in) :: a,b | |
real(8), dimension(size(a,1),size(b,2)) :: fvn_op_d_ix | 253 | 261 | real(8), dimension(size(a,1),size(b,2)) :: fvn_op_d_ix | |
fvn_op_d_ix=matmul(fvn_op_d_matinv(a),b) | 254 | 262 | fvn_op_d_ix=matmul(fvn_op_d_matinv(a),b) | |
end function | 255 | 263 | end function | |
function fvn_op_c_ix(a,b) | 256 | 264 | function fvn_op_c_ix(a,b) | |
implicit none | 257 | 265 | implicit none | |
complex(4), dimension(:,:), intent(in) :: a,b | 258 | 266 | complex(4), dimension(:,:), intent(in) :: a,b | |
complex(4), dimension(size(a,1),size(b,2)) :: fvn_op_c_ix | 259 | 267 | complex(4), dimension(size(a,1),size(b,2)) :: fvn_op_c_ix | |
fvn_op_c_ix=matmul(fvn_op_c_matinv(a),b) | 260 | 268 | fvn_op_c_ix=matmul(fvn_op_c_matinv(a),b) | |
end function | 261 | 269 | end function | |
function fvn_op_z_ix(a,b) | 262 | 270 | function fvn_op_z_ix(a,b) | |
implicit none | 263 | 271 | implicit none | |
complex(8), dimension(:,:), intent(in) :: a,b | 264 | 272 | complex(8), dimension(:,:), intent(in) :: a,b | |
complex(8), dimension(size(a,1),size(b,2)) :: fvn_op_z_ix | 265 | 273 | complex(8), dimension(size(a,1),size(b,2)) :: fvn_op_z_ix | |
fvn_op_z_ix=matmul(fvn_op_z_matinv(a),b) | 266 | 274 | fvn_op_z_ix=matmul(fvn_op_z_matinv(a),b) | |
end function | 267 | 275 | end function | |
268 | 276 | |||
! | 269 | 277 | ! | |
! .xi. | 270 | 278 | ! .xi. | |
! | 271 | 279 | ! | |
function fvn_op_s_xi(a,b) | 272 | 280 | function fvn_op_s_xi(a,b) | |
implicit none | 273 | 281 | implicit none | |
real(4), dimension(:,:), intent(in) :: a,b | 274 | 282 | real(4), dimension(:,:), intent(in) :: a,b | |
real(4), dimension(size(a,1),size(b,2)) :: fvn_op_s_xi | 275 | 283 | real(4), dimension(size(a,1),size(b,2)) :: fvn_op_s_xi | |
fvn_op_s_xi=matmul(a,fvn_op_s_matinv(b)) | 276 | 284 | fvn_op_s_xi=matmul(a,fvn_op_s_matinv(b)) | |
end function | 277 | 285 | end function | |
function fvn_op_d_xi(a,b) | 278 | 286 | function fvn_op_d_xi(a,b) | |
implicit none | 279 | 287 | implicit none | |
real(8), dimension(:,:), intent(in) :: a,b | 280 | 288 | real(8), dimension(:,:), intent(in) :: a,b | |
real(8), dimension(size(a,1),size(b,2)) :: fvn_op_d_xi | 281 | 289 | real(8), dimension(size(a,1),size(b,2)) :: fvn_op_d_xi | |
fvn_op_d_xi=matmul(a,fvn_op_d_matinv(b)) | 282 | 290 | fvn_op_d_xi=matmul(a,fvn_op_d_matinv(b)) | |
end function | 283 | 291 | end function | |
function fvn_op_c_xi(a,b) | 284 | 292 | function fvn_op_c_xi(a,b) | |
implicit none | 285 | 293 | implicit none | |
complex(4), dimension(:,:), intent(in) :: a,b | 286 | 294 | complex(4), dimension(:,:), intent(in) :: a,b | |
complex(4), dimension(size(a,1),size(b,2)) :: fvn_op_c_xi | 287 | 295 | complex(4), dimension(size(a,1),size(b,2)) :: fvn_op_c_xi | |
fvn_op_c_xi=matmul(a,fvn_op_c_matinv(b)) | 288 | 296 | fvn_op_c_xi=matmul(a,fvn_op_c_matinv(b)) | |
end function | 289 | 297 | end function | |
function fvn_op_z_xi(a,b) | 290 | 298 | function fvn_op_z_xi(a,b) | |
implicit none | 291 | 299 | implicit none | |
complex(8), dimension(:,:), intent(in) :: a,b | 292 | 300 | complex(8), dimension(:,:), intent(in) :: a,b | |
complex(8), dimension(size(a,1),size(b,2)) :: fvn_op_z_xi | 293 | 301 | complex(8), dimension(size(a,1),size(b,2)) :: fvn_op_z_xi | |
fvn_op_z_xi=matmul(a,fvn_op_z_matinv(b)) | 294 | 302 | fvn_op_z_xi=matmul(a,fvn_op_z_matinv(b)) | |
end function | 295 | 303 | end function | |
296 | 304 | |||
! | 297 | 305 | ! | |
! .h. | 298 | 306 | ! .h. | |
! | 299 | 307 | ! | |
function fvn_op_c_conj_transpose(a) | 300 | 308 | function fvn_op_c_conj_transpose(a) | |
implicit none | 301 | 309 | implicit none | |
complex(4),dimension(:,:),intent(in) :: a | 302 | 310 | complex(4),dimension(:,:),intent(in) :: a | |
complex(4),dimension(size(a,2),size(a,1)) :: fvn_op_c_conj_transpose | 303 | 311 | complex(4),dimension(size(a,2),size(a,1)) :: fvn_op_c_conj_transpose | |
fvn_op_c_conj_transpose=transpose(conjg(a)) | 304 | 312 | fvn_op_c_conj_transpose=transpose(conjg(a)) | |
end function | 305 | 313 | end function | |
function fvn_op_z_conj_transpose(a) | 306 | 314 | function fvn_op_z_conj_transpose(a) | |
implicit none | 307 | 315 | implicit none | |
complex(8),dimension(:,:),intent(in) :: a | 308 | 316 | complex(8),dimension(:,:),intent(in) :: a | |
complex(8),dimension(size(a,2),size(a,1)) :: fvn_op_z_conj_transpose | 309 | 317 | complex(8),dimension(size(a,2),size(a,1)) :: fvn_op_z_conj_transpose | |
fvn_op_z_conj_transpose=transpose(conjg(a)) | 310 | 318 | fvn_op_z_conj_transpose=transpose(conjg(a)) | |
end function | 311 | 319 | end function | |
312 | 320 | |||
313 | 321 | |||
! | 314 | 322 | ! | |
! .hx. | 315 | 323 | ! .hx. | |
! | 316 | 324 | ! | |
function fvn_op_c_hx(a,b) | 317 | 325 | function fvn_op_c_hx(a,b) | |
implicit none | 318 | 326 | implicit none | |
complex(4), dimension(:,:), intent(in) :: a,b | 319 | 327 | complex(4), dimension(:,:), intent(in) :: a,b | |
complex(4), dimension(size(a,2),size(b,2)) :: fvn_op_c_hx | 320 | 328 | complex(4), dimension(size(a,2),size(b,2)) :: fvn_op_c_hx | |
fvn_op_c_hx=matmul(transpose(conjg(a)),b) | 321 | 329 | fvn_op_c_hx=matmul(transpose(conjg(a)),b) | |
end function | 322 | 330 | end function | |
function fvn_op_z_hx(a,b) | 323 | 331 | function fvn_op_z_hx(a,b) | |
implicit none | 324 | 332 | implicit none | |
complex(8), dimension(:,:), intent(in) :: a,b | 325 | 333 | complex(8), dimension(:,:), intent(in) :: a,b | |
complex(8), dimension(size(a,2),size(b,2)) :: fvn_op_z_hx | 326 | 334 | complex(8), dimension(size(a,2),size(b,2)) :: fvn_op_z_hx | |
fvn_op_z_hx=matmul(transpose(conjg(a)),b) | 327 | 335 | fvn_op_z_hx=matmul(transpose(conjg(a)),b) | |
end function | 328 | 336 | end function | |
329 | 337 | |||
330 | 338 | |||
! | 331 | 339 | ! | |
! .xh. | 332 | 340 | ! .xh. | |
! | 333 | 341 | ! | |
function fvn_op_c_xh(a,b) | 334 | 342 | function fvn_op_c_xh(a,b) | |
implicit none | 335 | 343 | implicit none | |
complex(4), dimension(:,:), intent(in) :: a,b | 336 | 344 | complex(4), dimension(:,:), intent(in) :: a,b | |
complex(4), dimension(size(a,1),size(b,1)) :: fvn_op_c_xh | 337 | 345 | complex(4), dimension(size(a,1),size(b,1)) :: fvn_op_c_xh | |
fvn_op_c_xh=matmul(a,transpose(conjg(b))) | 338 | 346 | fvn_op_c_xh=matmul(a,transpose(conjg(b))) | |
end function | 339 | 347 | end function | |
function fvn_op_z_xh(a,b) | 340 | 348 | function fvn_op_z_xh(a,b) | |
implicit none | 341 | 349 | implicit none | |
complex(8), dimension(:,:), intent(in) :: a,b | 342 | 350 | complex(8), dimension(:,:), intent(in) :: a,b | |
complex(8), dimension(size(a,1),size(b,1)) :: fvn_op_z_xh | 343 | 351 | complex(8), dimension(size(a,1),size(b,1)) :: fvn_op_z_xh | |
fvn_op_z_xh=matmul(a,transpose(conjg(b))) | 344 | 352 | fvn_op_z_xh=matmul(a,transpose(conjg(b))) | |
end function | 345 | 353 | end function | |
346 | 354 | |||
347 | 355 | |||
348 | 356 | |||
349 | 357 | |||
350 | 358 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 351 | 359 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 352 | 360 | ! | |
! Identity Matrix | 353 | 361 | ! Identity Matrix | |
! | 354 | 362 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 355 | 363 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
function fvn_d_ident(n) | 356 | 364 | function fvn_d_ident(n) | |
implicit none | 357 | 365 | implicit none | |
integer(kind=4) :: n | 358 | 366 | integer(kind=4) :: n | |
real(kind=8), dimension(n,n) :: fvn_d_ident | 359 | 367 | real(kind=8), dimension(n,n) :: fvn_d_ident | |
360 | 368 | |||
real(kind=8),dimension(n*n) :: vect | 361 | 369 | real(kind=8),dimension(n*n) :: vect | |
integer(kind=4) :: i | 362 | 370 | integer(kind=4) :: i | |
363 | 371 | |||
vect=0._8 | 364 | 372 | vect=0._8 | |
vect(1:n*n:n+1) = 1._8 | 365 | 373 | vect(1:n*n:n+1) = 1._8 | |
fvn_d_ident=reshape(vect, shape = (/ n,n /)) | 366 | 374 | fvn_d_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 367 | 375 | end function | |
368 | 376 | |||
function fvn_s_ident(n) | 369 | 377 | function fvn_s_ident(n) | |
implicit none | 370 | 378 | implicit none | |
integer(kind=4) :: n | 371 | 379 | integer(kind=4) :: n | |
real(kind=4), dimension(n,n) :: fvn_s_ident | 372 | 380 | real(kind=4), dimension(n,n) :: fvn_s_ident | |
373 | 381 | |||
real(kind=4),dimension(n*n) :: vect | 374 | 382 | real(kind=4),dimension(n*n) :: vect | |
integer(kind=4) :: i | 375 | 383 | integer(kind=4) :: i | |
376 | 384 | |||
vect=0._4 | 377 | 385 | vect=0._4 | |
vect(1:n*n:n+1) = 1._4 | 378 | 386 | vect(1:n*n:n+1) = 1._4 | |
fvn_s_ident=reshape(vect, shape = (/ n,n /)) | 379 | 387 | fvn_s_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 380 | 388 | end function | |
381 | 389 | |||
function fvn_c_ident(n) | 382 | 390 | function fvn_c_ident(n) | |
implicit none | 383 | 391 | implicit none | |
integer(kind=4) :: n | 384 | 392 | integer(kind=4) :: n | |
complex(kind=4), dimension(n,n) :: fvn_c_ident | 385 | 393 | complex(kind=4), dimension(n,n) :: fvn_c_ident | |
386 | 394 | |||
complex(kind=4),dimension(n*n) :: vect | 387 | 395 | complex(kind=4),dimension(n*n) :: vect | |
integer(kind=4) :: i | 388 | 396 | integer(kind=4) :: i | |
389 | 397 | |||
vect=(0._4,0._4) | 390 | 398 | vect=(0._4,0._4) | |
vect(1:n*n:n+1) = (1._4,0._4) | 391 | 399 | vect(1:n*n:n+1) = (1._4,0._4) | |
fvn_c_ident=reshape(vect, shape = (/ n,n /)) | 392 | 400 | fvn_c_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 393 | 401 | end function | |
394 | 402 | |||
function fvn_z_ident(n) | 395 | 403 | function fvn_z_ident(n) | |
implicit none | 396 | 404 | implicit none | |
integer(kind=4) :: n | 397 | 405 | integer(kind=4) :: n | |
complex(kind=8), dimension(n,n) :: fvn_z_ident | 398 | 406 | complex(kind=8), dimension(n,n) :: fvn_z_ident | |
399 | 407 | |||
complex(kind=8),dimension(n*n) :: vect | 400 | 408 | complex(kind=8),dimension(n*n) :: vect | |
integer(kind=4) :: i | 401 | 409 | integer(kind=4) :: i | |
402 | 410 | |||
vect=(0._8,0._8) | 403 | 411 | vect=(0._8,0._8) | |
vect(1:n*n:n+1) = (1._8,0._8) | 404 | 412 | vect(1:n*n:n+1) = (1._8,0._8) | |
fvn_z_ident=reshape(vect, shape = (/ n,n /)) | 405 | 413 | fvn_z_ident=reshape(vect, shape = (/ n,n /)) | |
end function | 406 | 414 | end function | |
407 | 415 | |||
408 | 416 | |||
409 | 417 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 410 | 418 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 411 | 419 | ! | |
! Matrix inversion subroutines | 412 | 420 | ! Matrix inversion subroutines | |
! | 413 | 421 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 414 | 422 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
415 | 423 | |||
subroutine fvn_s_matinv(d,a,inva,status) | 416 | 424 | subroutine fvn_s_matinv(d,a,inva,status) | |
! | 417 | 425 | ! | |
! Matrix inversion of a real matrix using BLAS and LAPACK | 418 | 426 | ! Matrix inversion of a real matrix using BLAS and LAPACK | |
! | 419 | 427 | ! | |
! d (in) : matrix rank | 420 | 428 | ! d (in) : matrix rank | |
! a (in) : input matrix | 421 | 429 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 422 | 430 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 423 | 431 | ! status (ou) : =0 if something failed | |
! | 424 | 432 | ! | |
implicit none | 425 | 433 | implicit none | |
integer, intent(in) :: d | 426 | 434 | integer, intent(in) :: d | |
real, intent(in) :: a(d,d) | 427 | 435 | real, intent(in) :: a(d,d) | |
real, intent(out) :: inva(d,d) | 428 | 436 | real, intent(out) :: inva(d,d) | |
integer, intent(out),optional :: status | 429 | 437 | integer, intent(out),optional :: status | |
430 | 438 | |||
integer, allocatable :: ipiv(:) | 431 | 439 | integer, allocatable :: ipiv(:) | |
real, allocatable :: work(:) | 432 | 440 | real, allocatable :: work(:) | |
real twork(1) | 433 | 441 | real twork(1) | |
integer :: info | 434 | 442 | integer :: info | |
integer :: lwork | 435 | 443 | integer :: lwork | |
436 | 444 | |||
if (present(status)) status=1 | 437 | 445 | if (present(status)) status=1 | |
438 | 446 | |||
allocate(ipiv(d)) | 439 | 447 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 440 | 448 | ! copy a into inva using BLAS | |
!call scopy(d*d,a,1,inva,1) | 441 | 449 | !call scopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 442 | 450 | inva(:,:)=a(:,:) | |
! LU factorization using LAPACK | 443 | 451 | ! LU factorization using LAPACK | |
call sgetrf(d,d,inva,d,ipiv,info) | 444 | 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 | 445 | 453 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 446 | 454 | if (info /= 0) then | |
if (present(status)) status=0 | 447 | 455 | if (present(status)) status=0 | |
deallocate(ipiv) | 448 | 456 | deallocate(ipiv) | |
return | 449 | 457 | return | |
end if | 450 | 458 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 451 | 459 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call sgetri(d,inva,d,ipiv,twork,-1,info) | 452 | 460 | call sgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 453 | 461 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 454 | 462 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 455 | 463 | ! Matrix inversion using LAPACK | |
call sgetri(d,inva,d,ipiv,work,lwork,info) | 456 | 464 | call sgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 457 | 465 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 458 | 466 | if (info /= 0) then | |
if (present(status)) status=0 | 459 | 467 | if (present(status)) status=0 | |
end if | 460 | 468 | end if | |
deallocate(work) | 461 | 469 | deallocate(work) | |
deallocate(ipiv) | 462 | 470 | deallocate(ipiv) | |
end subroutine | 463 | 471 | end subroutine | |
464 | 472 | |||
subroutine fvn_d_matinv(d,a,inva,status) | 465 | 473 | subroutine fvn_d_matinv(d,a,inva,status) | |
! | 466 | 474 | ! | |
! Matrix inversion of a double precision matrix using BLAS and LAPACK | 467 | 475 | ! Matrix inversion of a double precision matrix using BLAS and LAPACK | |
! | 468 | 476 | ! | |
! d (in) : matrix rank | 469 | 477 | ! d (in) : matrix rank | |
! a (in) : input matrix | 470 | 478 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 471 | 479 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 472 | 480 | ! status (ou) : =0 if something failed | |
! | 473 | 481 | ! | |
implicit none | 474 | 482 | implicit none | |
integer, intent(in) :: d | 475 | 483 | integer, intent(in) :: d | |
double precision, intent(in) :: a(d,d) | 476 | 484 | double precision, intent(in) :: a(d,d) | |
double precision, intent(out) :: inva(d,d) | 477 | 485 | double precision, intent(out) :: inva(d,d) | |
integer, intent(out),optional :: status | 478 | 486 | integer, intent(out),optional :: status | |
479 | 487 | |||
integer, allocatable :: ipiv(:) | 480 | 488 | integer, allocatable :: ipiv(:) | |
double precision, allocatable :: work(:) | 481 | 489 | double precision, allocatable :: work(:) | |
double precision :: twork(1) | 482 | 490 | double precision :: twork(1) | |
integer :: info | 483 | 491 | integer :: info | |
integer :: lwork | 484 | 492 | integer :: lwork | |
485 | 493 | |||
if (present(status)) status=1 | 486 | 494 | if (present(status)) status=1 | |
487 | 495 | |||
allocate(ipiv(d)) | 488 | 496 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 489 | 497 | ! copy a into inva using BLAS | |
!call dcopy(d*d,a,1,inva,1) | 490 | 498 | !call dcopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 491 | 499 | inva(:,:)=a(:,:) | |
! LU factorization using LAPACK | 492 | 500 | ! LU factorization using LAPACK | |
call dgetrf(d,d,inva,d,ipiv,info) | 493 | 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 | 494 | 502 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 495 | 503 | if (info /= 0) then | |
if (present(status)) status=0 | 496 | 504 | if (present(status)) status=0 | |
deallocate(ipiv) | 497 | 505 | deallocate(ipiv) | |
return | 498 | 506 | return | |
end if | 499 | 507 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 500 | 508 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call dgetri(d,inva,d,ipiv,twork,-1,info) | 501 | 509 | call dgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 502 | 510 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 503 | 511 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 504 | 512 | ! Matrix inversion using LAPACK | |
call dgetri(d,inva,d,ipiv,work,lwork,info) | 505 | 513 | call dgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 506 | 514 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 507 | 515 | if (info /= 0) then | |
if (present(status)) status=0 | 508 | 516 | if (present(status)) status=0 | |
end if | 509 | 517 | end if | |
deallocate(work) | 510 | 518 | deallocate(work) | |
deallocate(ipiv) | 511 | 519 | deallocate(ipiv) | |
end subroutine | 512 | 520 | end subroutine | |
513 | 521 | |||
subroutine fvn_c_matinv(d,a,inva,status) | 514 | 522 | subroutine fvn_c_matinv(d,a,inva,status) | |
! | 515 | 523 | ! | |
! Matrix inversion of a complex matrix using BLAS and LAPACK | 516 | 524 | ! Matrix inversion of a complex matrix using BLAS and LAPACK | |
! | 517 | 525 | ! | |
! d (in) : matrix rank | 518 | 526 | ! d (in) : matrix rank | |
! a (in) : input matrix | 519 | 527 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 520 | 528 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 521 | 529 | ! status (ou) : =0 if something failed | |
! | 522 | 530 | ! | |
implicit none | 523 | 531 | implicit none | |
integer, intent(in) :: d | 524 | 532 | integer, intent(in) :: d | |
complex, intent(in) :: a(d,d) | 525 | 533 | complex, intent(in) :: a(d,d) | |
complex, intent(out) :: inva(d,d) | 526 | 534 | complex, intent(out) :: inva(d,d) | |
integer, intent(out),optional :: status | 527 | 535 | integer, intent(out),optional :: status | |
528 | 536 | |||
integer, allocatable :: ipiv(:) | 529 | 537 | integer, allocatable :: ipiv(:) | |
complex, allocatable :: work(:) | 530 | 538 | complex, allocatable :: work(:) | |
complex :: twork(1) | 531 | 539 | complex :: twork(1) | |
integer :: info | 532 | 540 | integer :: info | |
integer :: lwork | 533 | 541 | integer :: lwork | |
534 | 542 | |||
if (present(status)) status=1 | 535 | 543 | if (present(status)) status=1 | |
536 | 544 | |||
allocate(ipiv(d)) | 537 | 545 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 538 | 546 | ! copy a into inva using BLAS | |
!call ccopy(d*d,a,1,inva,1) | 539 | 547 | !call ccopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 540 | 548 | inva(:,:)=a(:,:) | |
541 | 549 | |||
! LU factorization using LAPACK | 542 | 550 | ! LU factorization using LAPACK | |
call cgetrf(d,d,inva,d,ipiv,info) | 543 | 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 | 544 | 552 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 545 | 553 | if (info /= 0) then | |
if (present(status)) status=0 | 546 | 554 | if (present(status)) status=0 | |
deallocate(ipiv) | 547 | 555 | deallocate(ipiv) | |
return | 548 | 556 | return | |
end if | 549 | 557 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 550 | 558 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call cgetri(d,inva,d,ipiv,twork,-1,info) | 551 | 559 | call cgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 552 | 560 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 553 | 561 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 554 | 562 | ! Matrix inversion using LAPACK | |
call cgetri(d,inva,d,ipiv,work,lwork,info) | 555 | 563 | call cgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 556 | 564 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 557 | 565 | if (info /= 0) then | |
if (present(status)) status=0 | 558 | 566 | if (present(status)) status=0 | |
end if | 559 | 567 | end if | |
deallocate(work) | 560 | 568 | deallocate(work) | |
deallocate(ipiv) | 561 | 569 | deallocate(ipiv) | |
end subroutine | 562 | 570 | end subroutine | |
563 | 571 | |||
subroutine fvn_z_matinv(d,a,inva,status) | 564 | 572 | subroutine fvn_z_matinv(d,a,inva,status) | |
! | 565 | 573 | ! | |
! Matrix inversion of a double complex matrix using BLAS and LAPACK | 566 | 574 | ! Matrix inversion of a double complex matrix using BLAS and LAPACK | |
! | 567 | 575 | ! | |
! d (in) : matrix rank | 568 | 576 | ! d (in) : matrix rank | |
! a (in) : input matrix | 569 | 577 | ! a (in) : input matrix | |
! inva (out) : inversed matrix | 570 | 578 | ! inva (out) : inversed matrix | |
! status (ou) : =0 if something failed | 571 | 579 | ! status (ou) : =0 if something failed | |
! | 572 | 580 | ! | |
implicit none | 573 | 581 | implicit none | |
integer, intent(in) :: d | 574 | 582 | integer, intent(in) :: d | |
double complex, intent(in) :: a(d,d) | 575 | 583 | double complex, intent(in) :: a(d,d) | |
double complex, intent(out) :: inva(d,d) | 576 | 584 | double complex, intent(out) :: inva(d,d) | |
integer, intent(out),optional :: status | 577 | 585 | integer, intent(out),optional :: status | |
578 | 586 | |||
integer, allocatable :: ipiv(:) | 579 | 587 | integer, allocatable :: ipiv(:) | |
double complex, allocatable :: work(:) | 580 | 588 | double complex, allocatable :: work(:) | |
double complex :: twork(1) | 581 | 589 | double complex :: twork(1) | |
integer :: info | 582 | 590 | integer :: info | |
integer :: lwork | 583 | 591 | integer :: lwork | |
584 | 592 | |||
if (present(status)) status=1 | 585 | 593 | if (present(status)) status=1 | |
586 | 594 | |||
allocate(ipiv(d)) | 587 | 595 | allocate(ipiv(d)) | |
! copy a into inva using BLAS | 588 | 596 | ! copy a into inva using BLAS | |
!call zcopy(d*d,a,1,inva,1) | 589 | 597 | !call zcopy(d*d,a,1,inva,1) | |
inva(:,:)=a(:,:) | 590 | 598 | inva(:,:)=a(:,:) | |
591 | 599 | |||
! LU factorization using LAPACK | 592 | 600 | ! LU factorization using LAPACK | |
call zgetrf(d,d,inva,d,ipiv,info) | 593 | 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 | 594 | 602 | ! if info is not equal to 0, something went wrong we exit setting status to 0 | |
if (info /= 0) then | 595 | 603 | if (info /= 0) then | |
if (present(status)) status=0 | 596 | 604 | if (present(status)) status=0 | |
deallocate(ipiv) | 597 | 605 | deallocate(ipiv) | |
return | 598 | 606 | return | |
end if | 599 | 607 | end if | |
! we use the query fonction of xxxtri to obtain the optimal workspace size | 600 | 608 | ! we use the query fonction of xxxtri to obtain the optimal workspace size | |
call zgetri(d,inva,d,ipiv,twork,-1,info) | 601 | 609 | call zgetri(d,inva,d,ipiv,twork,-1,info) | |
lwork=int(twork(1)) | 602 | 610 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 603 | 611 | allocate(work(lwork)) | |
! Matrix inversion using LAPACK | 604 | 612 | ! Matrix inversion using LAPACK | |
call zgetri(d,inva,d,ipiv,work,lwork,info) | 605 | 613 | call zgetri(d,inva,d,ipiv,work,lwork,info) | |
! again if info is not equal to 0, we exit setting status to 0 | 606 | 614 | ! again if info is not equal to 0, we exit setting status to 0 | |
if (info /= 0) then | 607 | 615 | if (info /= 0) then | |
if (present(status)) status=0 | 608 | 616 | if (present(status)) status=0 | |
end if | 609 | 617 | end if | |
deallocate(work) | 610 | 618 | deallocate(work) | |
deallocate(ipiv) | 611 | 619 | deallocate(ipiv) | |
end subroutine | 612 | 620 | end subroutine | |
613 | 621 | |||
614 | 622 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 615 | 623 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 616 | 624 | ! | |
! Determinants | 617 | 625 | ! Determinants | |
! | 618 | 626 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 619 | 627 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
function fvn_s_det(d,a,status) | 620 | 628 | function fvn_s_det(d,a,status) | |
! | 621 | 629 | ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 622 | 630 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 623 | 631 | ! | |
! d (in) : matrix rank | 624 | 632 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 625 | 633 | ! a (in) : The Matrix | |
! status (out) : =0 if LU factorization failed | 626 | 634 | ! status (out) : =0 if LU factorization failed | |
! | 627 | 635 | ! | |
implicit none | 628 | 636 | implicit none | |
integer, intent(in) :: d | 629 | 637 | integer, intent(in) :: d | |
real, intent(in) :: a(d,d) | 630 | 638 | real, intent(in) :: a(d,d) | |
integer, intent(out), optional :: status | 631 | 639 | integer, intent(out), optional :: status | |
real :: fvn_s_det | 632 | 640 | real :: fvn_s_det | |
633 | 641 | |||
real, allocatable :: wc_a(:,:) | 634 | 642 | real, allocatable :: wc_a(:,:) | |
integer, allocatable :: ipiv(:) | 635 | 643 | integer, allocatable :: ipiv(:) | |
integer :: info,i | 636 | 644 | integer :: info,i | |
637 | 645 | |||
if (present(status)) status=1 | 638 | 646 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 639 | 647 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 640 | 648 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 641 | 649 | wc_a(:,:)=a(:,:) | |
call sgetrf(d,d,wc_a,d,ipiv,info) | 642 | 650 | call sgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 643 | 651 | if (info/= 0) then | |
if (present(status)) status=0 | 644 | 652 | if (present(status)) status=0 | |
fvn_s_det=0.e0 | 645 | 653 | fvn_s_det=0.e0 | |
deallocate(ipiv) | 646 | 654 | deallocate(ipiv) | |
deallocate(wc_a) | 647 | 655 | deallocate(wc_a) | |
return | 648 | 656 | return | |
end if | 649 | 657 | end if | |
fvn_s_det=1.e0 | 650 | 658 | fvn_s_det=1.e0 | |
do i=1,d | 651 | 659 | do i=1,d | |
if (ipiv(i)==i) then | 652 | 660 | if (ipiv(i)==i) then | |
fvn_s_det=fvn_s_det*wc_a(i,i) | 653 | 661 | fvn_s_det=fvn_s_det*wc_a(i,i) | |
else | 654 | 662 | else | |
fvn_s_det=-fvn_s_det*wc_a(i,i) | 655 | 663 | fvn_s_det=-fvn_s_det*wc_a(i,i) | |
end if | 656 | 664 | end if | |
end do | 657 | 665 | end do | |
deallocate(ipiv) | 658 | 666 | deallocate(ipiv) | |
deallocate(wc_a) | 659 | 667 | deallocate(wc_a) | |
660 | 668 | |||
end function | 661 | 669 | end function | |
662 | 670 | |||
function fvn_d_det(d,a,status) | 663 | 671 | function fvn_d_det(d,a,status) | |
! | 664 | 672 | ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 665 | 673 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 666 | 674 | ! | |
! d (in) : matrix rank | 667 | 675 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 668 | 676 | ! a (in) : The Matrix | |
! status (out) : =0 if LU factorization failed | 669 | 677 | ! status (out) : =0 if LU factorization failed | |
! | 670 | 678 | ! | |
implicit none | 671 | 679 | implicit none | |
integer, intent(in) :: d | 672 | 680 | integer, intent(in) :: d | |
double precision, intent(in) :: a(d,d) | 673 | 681 | double precision, intent(in) :: a(d,d) | |
integer, intent(out), optional :: status | 674 | 682 | integer, intent(out), optional :: status | |
double precision :: fvn_d_det | 675 | 683 | double precision :: fvn_d_det | |
676 | 684 | |||
double precision, allocatable :: wc_a(:,:) | 677 | 685 | double precision, allocatable :: wc_a(:,:) | |
integer, allocatable :: ipiv(:) | 678 | 686 | integer, allocatable :: ipiv(:) | |
integer :: info,i | 679 | 687 | integer :: info,i | |
680 | 688 | |||
if (present(status)) status=1 | 681 | 689 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 682 | 690 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 683 | 691 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 684 | 692 | wc_a(:,:)=a(:,:) | |
call dgetrf(d,d,wc_a,d,ipiv,info) | 685 | 693 | call dgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 686 | 694 | if (info/= 0) then | |
if (present(status)) status=0 | 687 | 695 | if (present(status)) status=0 | |
fvn_d_det=0.d0 | 688 | 696 | fvn_d_det=0.d0 | |
deallocate(ipiv) | 689 | 697 | deallocate(ipiv) | |
deallocate(wc_a) | 690 | 698 | deallocate(wc_a) | |
return | 691 | 699 | return | |
end if | 692 | 700 | end if | |
fvn_d_det=1.d0 | 693 | 701 | fvn_d_det=1.d0 | |
do i=1,d | 694 | 702 | do i=1,d | |
if (ipiv(i)==i) then | 695 | 703 | if (ipiv(i)==i) then | |
fvn_d_det=fvn_d_det*wc_a(i,i) | 696 | 704 | fvn_d_det=fvn_d_det*wc_a(i,i) | |
else | 697 | 705 | else | |
fvn_d_det=-fvn_d_det*wc_a(i,i) | 698 | 706 | fvn_d_det=-fvn_d_det*wc_a(i,i) | |
end if | 699 | 707 | end if | |
end do | 700 | 708 | end do | |
deallocate(ipiv) | 701 | 709 | deallocate(ipiv) | |
deallocate(wc_a) | 702 | 710 | deallocate(wc_a) | |
703 | 711 | |||
end function | 704 | 712 | end function | |
705 | 713 | |||
function fvn_c_det(d,a,status) ! | 706 | 714 | function fvn_c_det(d,a,status) ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 707 | 715 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 708 | 716 | ! | |
! d (in) : matrix rank | 709 | 717 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 710 | 718 | ! a (in) : The Matrix | |
! status (out) : =0 if LU factorization failed | 711 | 719 | ! status (out) : =0 if LU factorization failed | |
! | 712 | 720 | ! | |
implicit none | 713 | 721 | implicit none | |
integer, intent(in) :: d | 714 | 722 | integer, intent(in) :: d | |
complex, intent(in) :: a(d,d) | 715 | 723 | complex, intent(in) :: a(d,d) | |
integer, intent(out), optional :: status | 716 | 724 | integer, intent(out), optional :: status | |
complex :: fvn_c_det | 717 | 725 | complex :: fvn_c_det | |
718 | 726 | |||
complex, allocatable :: wc_a(:,:) | 719 | 727 | complex, allocatable :: wc_a(:,:) | |
integer, allocatable :: ipiv(:) | 720 | 728 | integer, allocatable :: ipiv(:) | |
integer :: info,i | 721 | 729 | integer :: info,i | |
722 | 730 | |||
if (present(status)) status=1 | 723 | 731 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 724 | 732 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 725 | 733 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 726 | 734 | wc_a(:,:)=a(:,:) | |
call cgetrf(d,d,wc_a,d,ipiv,info) | 727 | 735 | call cgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 728 | 736 | if (info/= 0) then | |
if (present(status)) status=0 | 729 | 737 | if (present(status)) status=0 | |
fvn_c_det=(0.e0,0.e0) | 730 | 738 | fvn_c_det=(0.e0,0.e0) | |
deallocate(ipiv) | 731 | 739 | deallocate(ipiv) | |
deallocate(wc_a) | 732 | 740 | deallocate(wc_a) | |
return | 733 | 741 | return | |
end if | 734 | 742 | end if | |
fvn_c_det=(1.e0,0.e0) | 735 | 743 | fvn_c_det=(1.e0,0.e0) | |
do i=1,d | 736 | 744 | do i=1,d | |
if (ipiv(i)==i) then | 737 | 745 | if (ipiv(i)==i) then | |
fvn_c_det=fvn_c_det*wc_a(i,i) | 738 | 746 | fvn_c_det=fvn_c_det*wc_a(i,i) | |
else | 739 | 747 | else | |
fvn_c_det=-fvn_c_det*wc_a(i,i) | 740 | 748 | fvn_c_det=-fvn_c_det*wc_a(i,i) | |
end if | 741 | 749 | end if | |
end do | 742 | 750 | end do | |
deallocate(ipiv) | 743 | 751 | deallocate(ipiv) | |
deallocate(wc_a) | 744 | 752 | deallocate(wc_a) | |
745 | 753 | |||
end function | 746 | 754 | end function | |
747 | 755 | |||
function fvn_z_det(d,a,status) | 748 | 756 | function fvn_z_det(d,a,status) | |
! | 749 | 757 | ! | |
! Evaluate the determinant of a square matrix using lapack LU factorization | 750 | 758 | ! Evaluate the determinant of a square matrix using lapack LU factorization | |
! | 751 | 759 | ! | |
! d (in) : matrix rank | 752 | 760 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 753 | 761 | ! a (in) : The Matrix | |
! det (out) : determinant | 754 | 762 | ! det (out) : determinant | |
! status (out) : =0 if LU factorization failed | 755 | 763 | ! status (out) : =0 if LU factorization failed | |
! | 756 | 764 | ! | |
implicit none | 757 | 765 | implicit none | |
integer, intent(in) :: d | 758 | 766 | integer, intent(in) :: d | |
double complex, intent(in) :: a(d,d) | 759 | 767 | double complex, intent(in) :: a(d,d) | |
integer, intent(out), optional :: status | 760 | 768 | integer, intent(out), optional :: status | |
double complex :: fvn_z_det | 761 | 769 | double complex :: fvn_z_det | |
762 | 770 | |||
double complex, allocatable :: wc_a(:,:) | 763 | 771 | double complex, allocatable :: wc_a(:,:) | |
integer, allocatable :: ipiv(:) | 764 | 772 | integer, allocatable :: ipiv(:) | |
integer :: info,i | 765 | 773 | integer :: info,i | |
766 | 774 | |||
if (present(status)) status=1 | 767 | 775 | if (present(status)) status=1 | |
allocate(wc_a(d,d)) | 768 | 776 | allocate(wc_a(d,d)) | |
allocate(ipiv(d)) | 769 | 777 | allocate(ipiv(d)) | |
wc_a(:,:)=a(:,:) | 770 | 778 | wc_a(:,:)=a(:,:) | |
call zgetrf(d,d,wc_a,d,ipiv,info) | 771 | 779 | call zgetrf(d,d,wc_a,d,ipiv,info) | |
if (info/= 0) then | 772 | 780 | if (info/= 0) then | |
if (present(status)) status=0 | 773 | 781 | if (present(status)) status=0 | |
fvn_z_det=(0.d0,0.d0) | 774 | 782 | fvn_z_det=(0.d0,0.d0) | |
deallocate(ipiv) | 775 | 783 | deallocate(ipiv) | |
deallocate(wc_a) | 776 | 784 | deallocate(wc_a) | |
return | 777 | 785 | return | |
end if | 778 | 786 | end if | |
fvn_z_det=(1.d0,0.d0) | 779 | 787 | fvn_z_det=(1.d0,0.d0) | |
do i=1,d | 780 | 788 | do i=1,d | |
if (ipiv(i)==i) then | 781 | 789 | if (ipiv(i)==i) then | |
fvn_z_det=fvn_z_det*wc_a(i,i) | 782 | 790 | fvn_z_det=fvn_z_det*wc_a(i,i) | |
else | 783 | 791 | else | |
fvn_z_det=-fvn_z_det*wc_a(i,i) | 784 | 792 | fvn_z_det=-fvn_z_det*wc_a(i,i) | |
end if | 785 | 793 | end if | |
end do | 786 | 794 | end do | |
deallocate(ipiv) | 787 | 795 | deallocate(ipiv) | |
deallocate(wc_a) | 788 | 796 | deallocate(wc_a) | |
789 | 797 | |||
end function | 790 | 798 | end function | |
791 | 799 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 792 | 800 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 793 | 801 | ! | |
! Condition test | 794 | 802 | ! Condition test | |
! | 795 | 803 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 796 | 804 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! 1-norm | 797 | 805 | ! 1-norm | |
! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm | 798 | 806 | ! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm | |
! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond | 799 | 807 | ! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond | |
! | 800 | 808 | ! | |
subroutine fvn_s_matcon(d,a,rcond,status) | 801 | 809 | subroutine fvn_s_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 802 | 810 | ! Matrix condition (reciprocal of condition number) | |
! | 803 | 811 | ! | |
! d (in) : matrix rank | 804 | 812 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 805 | 813 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 806 | 814 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 807 | 815 | ! status (out) : =0 if something went wrong | |
! | 808 | 816 | ! | |
implicit none | 809 | 817 | implicit none | |
integer, intent(in) :: d | 810 | 818 | integer, intent(in) :: d | |
real, intent(in) :: a(d,d) | 811 | 819 | real, intent(in) :: a(d,d) | |
real, intent(out) :: rcond | 812 | 820 | real, intent(out) :: rcond | |
integer, intent(out), optional :: status | 813 | 821 | integer, intent(out), optional :: status | |
814 | 822 | |||
real, allocatable :: work(:) | 815 | 823 | real, allocatable :: work(:) | |
integer, allocatable :: iwork(:) | 816 | 824 | integer, allocatable :: iwork(:) | |
real :: anorm | 817 | 825 | real :: anorm | |
real, allocatable :: wc_a(:,:) ! working copy of a | 818 | 826 | real, allocatable :: wc_a(:,:) ! working copy of a | |
integer :: info | 819 | 827 | integer :: info | |
integer, allocatable :: ipiv(:) | 820 | 828 | integer, allocatable :: ipiv(:) | |
821 | 829 | |||
real, external :: slange | 822 | 830 | real, external :: slange | |
823 | 831 | |||
824 | 832 | |||
if (present(status)) status=1 | 825 | 833 | if (present(status)) status=1 | |
826 | 834 | |||
anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | 827 | 835 | anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | |
828 | 836 | |||
allocate(wc_a(d,d)) | 829 | 837 | allocate(wc_a(d,d)) | |
!call scopy(d*d,a,1,wc_a,1) | 830 | 838 | !call scopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 831 | 839 | wc_a(:,:)=a(:,:) | |
832 | 840 | |||
allocate(ipiv(d)) | 833 | 841 | allocate(ipiv(d)) | |
call sgetrf(d,d,wc_a,d,ipiv,info) | 834 | 842 | call sgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 835 | 843 | if (info /= 0) then | |
if (present(status)) status=0 | 836 | 844 | if (present(status)) status=0 | |
deallocate(ipiv) | 837 | 845 | deallocate(ipiv) | |
deallocate(wc_a) | 838 | 846 | deallocate(wc_a) | |
return | 839 | 847 | return | |
end if | 840 | 848 | end if | |
allocate(work(4*d)) | 841 | 849 | allocate(work(4*d)) | |
allocate(iwork(d)) | 842 | 850 | allocate(iwork(d)) | |
call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | 843 | 851 | call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | |
if (info /= 0) then | 844 | 852 | if (info /= 0) then | |
if (present(status)) status=0 | 845 | 853 | if (present(status)) status=0 | |
end if | 846 | 854 | end if | |
deallocate(iwork) | 847 | 855 | deallocate(iwork) | |
deallocate(work) | 848 | 856 | deallocate(work) | |
deallocate(ipiv) | 849 | 857 | deallocate(ipiv) | |
deallocate(wc_a) | 850 | 858 | deallocate(wc_a) | |
851 | 859 | |||
end subroutine | 852 | 860 | end subroutine | |
853 | 861 | |||
subroutine fvn_d_matcon(d,a,rcond,status) | 854 | 862 | subroutine fvn_d_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 855 | 863 | ! Matrix condition (reciprocal of condition number) | |
! | 856 | 864 | ! | |
! d (in) : matrix rank | 857 | 865 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 858 | 866 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 859 | 867 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 860 | 868 | ! status (out) : =0 if something went wrong | |
! | 861 | 869 | ! | |
implicit none | 862 | 870 | implicit none | |
integer, intent(in) :: d | 863 | 871 | integer, intent(in) :: d | |
double precision, intent(in) :: a(d,d) | 864 | 872 | double precision, intent(in) :: a(d,d) | |
double precision, intent(out) :: rcond | 865 | 873 | double precision, intent(out) :: rcond | |
integer, intent(out), optional :: status | 866 | 874 | integer, intent(out), optional :: status | |
867 | 875 | |||
double precision, allocatable :: work(:) | 868 | 876 | double precision, allocatable :: work(:) | |
integer, allocatable :: iwork(:) | 869 | 877 | integer, allocatable :: iwork(:) | |
double precision :: anorm | 870 | 878 | double precision :: anorm | |
double precision, allocatable :: wc_a(:,:) ! working copy of a | 871 | 879 | double precision, allocatable :: wc_a(:,:) ! working copy of a | |
integer :: info | 872 | 880 | integer :: info | |
integer, allocatable :: ipiv(:) | 873 | 881 | integer, allocatable :: ipiv(:) | |
874 | 882 | |||
double precision, external :: dlange | 875 | 883 | double precision, external :: dlange | |
876 | 884 | |||
877 | 885 | |||
if (present(status)) status=1 | 878 | 886 | if (present(status)) status=1 | |
879 | 887 | |||
anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | 880 | 888 | anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm | |
881 | 889 | |||
allocate(wc_a(d,d)) | 882 | 890 | allocate(wc_a(d,d)) | |
!call dcopy(d*d,a,1,wc_a,1) | 883 | 891 | !call dcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 884 | 892 | wc_a(:,:)=a(:,:) | |
885 | 893 | |||
allocate(ipiv(d)) | 886 | 894 | allocate(ipiv(d)) | |
call dgetrf(d,d,wc_a,d,ipiv,info) | 887 | 895 | call dgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 888 | 896 | if (info /= 0) then | |
if (present(status)) status=0 | 889 | 897 | if (present(status)) status=0 | |
deallocate(ipiv) | 890 | 898 | deallocate(ipiv) | |
deallocate(wc_a) | 891 | 899 | deallocate(wc_a) | |
return | 892 | 900 | return | |
end if | 893 | 901 | end if | |
894 | 902 | |||
allocate(work(4*d)) | 895 | 903 | allocate(work(4*d)) | |
allocate(iwork(d)) | 896 | 904 | allocate(iwork(d)) | |
call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | 897 | 905 | call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) | |
if (info /= 0) then | 898 | 906 | if (info /= 0) then | |
if (present(status)) status=0 | 899 | 907 | if (present(status)) status=0 | |
end if | 900 | 908 | end if | |
deallocate(iwork) | 901 | 909 | deallocate(iwork) | |
deallocate(work) | 902 | 910 | deallocate(work) | |
deallocate(ipiv) | 903 | 911 | deallocate(ipiv) | |
deallocate(wc_a) | 904 | 912 | deallocate(wc_a) | |
905 | 913 | |||
end subroutine | 906 | 914 | end subroutine | |
907 | 915 | |||
subroutine fvn_c_matcon(d,a,rcond,status) | 908 | 916 | subroutine fvn_c_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 909 | 917 | ! Matrix condition (reciprocal of condition number) | |
! | 910 | 918 | ! | |
! d (in) : matrix rank | 911 | 919 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 912 | 920 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 913 | 921 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 914 | 922 | ! status (out) : =0 if something went wrong | |
! | 915 | 923 | ! | |
implicit none | 916 | 924 | implicit none | |
integer, intent(in) :: d | 917 | 925 | integer, intent(in) :: d | |
complex, intent(in) :: a(d,d) | 918 | 926 | complex, intent(in) :: a(d,d) | |
real, intent(out) :: rcond | 919 | 927 | real, intent(out) :: rcond | |
integer, intent(out), optional :: status | 920 | 928 | integer, intent(out), optional :: status | |
921 | 929 | |||
real, allocatable :: rwork(:) | 922 | 930 | real, allocatable :: rwork(:) | |
complex, allocatable :: work(:) | 923 | 931 | complex, allocatable :: work(:) | |
integer, allocatable :: iwork(:) | 924 | 932 | integer, allocatable :: iwork(:) | |
real :: anorm | 925 | 933 | real :: anorm | |
complex, allocatable :: wc_a(:,:) ! working copy of a | 926 | 934 | complex, allocatable :: wc_a(:,:) ! working copy of a | |
integer :: info | 927 | 935 | integer :: info | |
integer, allocatable :: ipiv(:) | 928 | 936 | integer, allocatable :: ipiv(:) | |
929 | 937 | |||
real, external :: clange | 930 | 938 | real, external :: clange | |
931 | 939 | |||
932 | 940 | |||
if (present(status)) status=1 | 933 | 941 | if (present(status)) status=1 | |
934 | 942 | |||
anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | 935 | 943 | anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | |
936 | 944 | |||
allocate(wc_a(d,d)) | 937 | 945 | allocate(wc_a(d,d)) | |
!call ccopy(d*d,a,1,wc_a,1) | 938 | 946 | !call ccopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 939 | 947 | wc_a(:,:)=a(:,:) | |
940 | 948 | |||
allocate(ipiv(d)) | 941 | 949 | allocate(ipiv(d)) | |
call cgetrf(d,d,wc_a,d,ipiv,info) | 942 | 950 | call cgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 943 | 951 | if (info /= 0) then | |
if (present(status)) status=0 | 944 | 952 | if (present(status)) status=0 | |
deallocate(ipiv) | 945 | 953 | deallocate(ipiv) | |
deallocate(wc_a) | 946 | 954 | deallocate(wc_a) | |
return | 947 | 955 | return | |
end if | 948 | 956 | end if | |
allocate(work(2*d)) | 949 | 957 | allocate(work(2*d)) | |
allocate(rwork(2*d)) | 950 | 958 | allocate(rwork(2*d)) | |
call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | 951 | 959 | call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | |
if (info /= 0) then | 952 | 960 | if (info /= 0) then | |
if (present(status)) status=0 | 953 | 961 | if (present(status)) status=0 | |
end if | 954 | 962 | end if | |
deallocate(rwork) | 955 | 963 | deallocate(rwork) | |
deallocate(work) | 956 | 964 | deallocate(work) | |
deallocate(ipiv) | 957 | 965 | deallocate(ipiv) | |
deallocate(wc_a) | 958 | 966 | deallocate(wc_a) | |
end subroutine | 959 | 967 | end subroutine | |
960 | 968 | |||
subroutine fvn_z_matcon(d,a,rcond,status) | 961 | 969 | subroutine fvn_z_matcon(d,a,rcond,status) | |
! Matrix condition (reciprocal of condition number) | 962 | 970 | ! Matrix condition (reciprocal of condition number) | |
! | 963 | 971 | ! | |
! d (in) : matrix rank | 964 | 972 | ! d (in) : matrix rank | |
! a (in) : The Matrix | 965 | 973 | ! a (in) : The Matrix | |
! rcond (out) : guess what | 966 | 974 | ! rcond (out) : guess what | |
! status (out) : =0 if something went wrong | 967 | 975 | ! status (out) : =0 if something went wrong | |
! | 968 | 976 | ! | |
implicit none | 969 | 977 | implicit none | |
integer, intent(in) :: d | 970 | 978 | integer, intent(in) :: d | |
double complex, intent(in) :: a(d,d) | 971 | 979 | double complex, intent(in) :: a(d,d) | |
double precision, intent(out) :: rcond | 972 | 980 | double precision, intent(out) :: rcond | |
integer, intent(out), optional :: status | 973 | 981 | integer, intent(out), optional :: status | |
974 | 982 | |||
double complex, allocatable :: work(:) | 975 | 983 | double complex, allocatable :: work(:) | |
double precision, allocatable :: rwork(:) | 976 | 984 | double precision, allocatable :: rwork(:) | |
double precision :: anorm | 977 | 985 | double precision :: anorm | |
double complex, allocatable :: wc_a(:,:) ! working copy of a | 978 | 986 | double complex, allocatable :: wc_a(:,:) ! working copy of a | |
integer :: info | 979 | 987 | integer :: info | |
integer, allocatable :: ipiv(:) | 980 | 988 | integer, allocatable :: ipiv(:) | |
981 | 989 | |||
double precision, external :: zlange | 982 | 990 | double precision, external :: zlange | |
983 | 991 | |||
984 | 992 | |||
if (present(status)) status=1 | 985 | 993 | if (present(status)) status=1 | |
986 | 994 | |||
anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | 987 | 995 | anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm | |
988 | 996 | |||
allocate(wc_a(d,d)) | 989 | 997 | allocate(wc_a(d,d)) | |
!call zcopy(d*d,a,1,wc_a,1) | 990 | 998 | !call zcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 991 | 999 | wc_a(:,:)=a(:,:) | |
992 | 1000 | |||
allocate(ipiv(d)) | 993 | 1001 | allocate(ipiv(d)) | |
call zgetrf(d,d,wc_a,d,ipiv,info) | 994 | 1002 | call zgetrf(d,d,wc_a,d,ipiv,info) | |
if (info /= 0) then | 995 | 1003 | if (info /= 0) then | |
if (present(status)) status=0 | 996 | 1004 | if (present(status)) status=0 | |
deallocate(ipiv) | 997 | 1005 | deallocate(ipiv) | |
deallocate(wc_a) | 998 | 1006 | deallocate(wc_a) | |
return | 999 | 1007 | return | |
end if | 1000 | 1008 | end if | |
1001 | 1009 | |||
allocate(work(2*d)) | 1002 | 1010 | allocate(work(2*d)) | |
allocate(rwork(2*d)) | 1003 | 1011 | allocate(rwork(2*d)) | |
call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | 1004 | 1012 | call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) | |
if (info /= 0) then | 1005 | 1013 | if (info /= 0) then | |
if (present(status)) status=0 | 1006 | 1014 | if (present(status)) status=0 | |
end if | 1007 | 1015 | end if | |
deallocate(rwork) | 1008 | 1016 | deallocate(rwork) | |
deallocate(work) | 1009 | 1017 | deallocate(work) | |
deallocate(ipiv) | 1010 | 1018 | deallocate(ipiv) | |
deallocate(wc_a) | 1011 | 1019 | deallocate(wc_a) | |
end subroutine | 1012 | 1020 | end subroutine | |
1013 | 1021 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1014 | 1022 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 1015 | 1023 | ! | |
! Valeurs propres/ Vecteurs propre | 1016 | 1024 | ! Valeurs propres/ Vecteurs propre | |
! | 1017 | 1025 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1018 | 1026 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
1019 | 1027 | |||
subroutine fvn_s_matev(d,a,evala,eveca,status) | 1020 | 1028 | subroutine fvn_s_matev(d,a,evala,eveca,status) | |
! | 1021 | 1029 | ! | |
! integer d (in) : matrice rank | 1022 | 1030 | ! integer d (in) : matrice rank | |
! real a(d,d) (in) : The Matrix | 1023 | 1031 | ! real a(d,d) (in) : The Matrix | |
! complex evala(d) (out) : eigenvalues | 1024 | 1032 | ! complex evala(d) (out) : eigenvalues | |
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1025 | 1033 | ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer (out) : status =0 if something went wrong | 1026 | 1034 | ! integer (out) : status =0 if something went wrong | |
! | 1027 | 1035 | ! | |
! interfacing Lapack routine SGEEV | 1028 | 1036 | ! interfacing Lapack routine SGEEV | |
implicit none | 1029 | 1037 | implicit none | |
integer, intent(in) :: d | 1030 | 1038 | integer, intent(in) :: d | |
real, intent(in) :: a(d,d) | 1031 | 1039 | real, intent(in) :: a(d,d) | |
complex, intent(out) :: evala(d) | 1032 | 1040 | complex, intent(out) :: evala(d) | |
complex, intent(out) :: eveca(d,d) | 1033 | 1041 | complex, intent(out) :: eveca(d,d) | |
integer, intent(out), optional :: status | 1034 | 1042 | integer, intent(out), optional :: status | |
1035 | 1043 | |||
real, allocatable :: wc_a(:,:) ! a working copy of a | 1036 | 1044 | real, allocatable :: wc_a(:,:) ! a working copy of a | |
integer :: info | 1037 | 1045 | integer :: info | |
integer :: lwork | 1038 | 1046 | integer :: lwork | |
real, allocatable :: wr(:),wi(:) | 1039 | 1047 | real, allocatable :: wr(:),wi(:) | |
real :: vl ! unused but necessary for the call | 1040 | 1048 | real :: vl ! unused but necessary for the call | |
real, allocatable :: vr(:,:) | 1041 | 1049 | real, allocatable :: vr(:,:) | |
real, allocatable :: work(:) | 1042 | 1050 | real, allocatable :: work(:) | |
real :: twork(1) | 1043 | 1051 | real :: twork(1) | |
integer i | 1044 | 1052 | integer i | |
integer j | 1045 | 1053 | integer j | |
1046 | 1054 | |||
if (present(status)) status=1 | 1047 | 1055 | if (present(status)) status=1 | |
1048 | 1056 | |||
! making a working copy of a | 1049 | 1057 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1050 | 1058 | allocate(wc_a(d,d)) | |
!call scopy(d*d,a,1,wc_a,1) | 1051 | 1059 | !call scopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1052 | 1060 | wc_a(:,:)=a(:,:) | |
1053 | 1061 | |||
allocate(wr(d)) | 1054 | 1062 | allocate(wr(d)) | |
allocate(wi(d)) | 1055 | 1063 | allocate(wi(d)) | |
allocate(vr(d,d)) | 1056 | 1064 | allocate(vr(d,d)) | |
! query optimal work size | 1057 | 1065 | ! query optimal work size | |
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | 1058 | 1066 | call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | |
lwork=int(twork(1)) | 1059 | 1067 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1060 | 1068 | allocate(work(lwork)) | |
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | 1061 | 1069 | call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | |
1062 | 1070 | |||
if (info /= 0) then | 1063 | 1071 | if (info /= 0) then | |
if (present(status)) status=0 | 1064 | 1072 | if (present(status)) status=0 | |
deallocate(work) | 1065 | 1073 | deallocate(work) | |
deallocate(vr) | 1066 | 1074 | deallocate(vr) | |
deallocate(wi) | 1067 | 1075 | deallocate(wi) | |
deallocate(wr) | 1068 | 1076 | deallocate(wr) | |
deallocate(wc_a) | 1069 | 1077 | deallocate(wc_a) | |
return | 1070 | 1078 | return | |
end if | 1071 | 1079 | end if | |
1072 | 1080 | |||
! now fill in the results | 1073 | 1081 | ! now fill in the results | |
i=1 | 1074 | 1082 | i=1 | |
do while(i<=d) | 1075 | 1083 | do while(i<=d) | |
evala(i)=cmplx(wr(i),wi(i)) | 1076 | 1084 | evala(i)=cmplx(wr(i),wi(i)) | |
if (wi(i) == 0.) then ! eigenvalue is real | 1077 | 1085 | if (wi(i) == 0.) then ! eigenvalue is real | |
eveca(:,i)=cmplx(vr(:,i),0.) | 1078 | 1086 | eveca(:,i)=cmplx(vr(:,i),0.) | |
else ! eigenvalue is complex | 1079 | 1087 | else ! eigenvalue is complex | |
evala(i+1)=cmplx(wr(i+1),wi(i+1)) | 1080 | 1088 | evala(i+1)=cmplx(wr(i+1),wi(i+1)) | |
eveca(:,i)=cmplx(vr(:,i),vr(:,i+1)) | 1081 | 1089 | eveca(:,i)=cmplx(vr(:,i),vr(:,i+1)) | |
eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1)) | 1082 | 1090 | eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1)) | |
i=i+1 | 1083 | 1091 | i=i+1 | |
end if | 1084 | 1092 | end if | |
i=i+1 | 1085 | 1093 | i=i+1 | |
enddo | 1086 | 1094 | enddo | |
deallocate(work) | 1087 | 1095 | deallocate(work) | |
deallocate(vr) | 1088 | 1096 | deallocate(vr) | |
deallocate(wi) | 1089 | 1097 | deallocate(wi) | |
deallocate(wr) | 1090 | 1098 | deallocate(wr) | |
deallocate(wc_a) | 1091 | 1099 | deallocate(wc_a) | |
1092 | 1100 | |||
end subroutine | 1093 | 1101 | end subroutine | |
1094 | 1102 | |||
subroutine fvn_d_matev(d,a,evala,eveca,status) | 1095 | 1103 | subroutine fvn_d_matev(d,a,evala,eveca,status) | |
! | 1096 | 1104 | ! | |
! integer d (in) : matrice rank | 1097 | 1105 | ! integer d (in) : matrice rank | |
! double precision a(d,d) (in) : The Matrix | 1098 | 1106 | ! double precision a(d,d) (in) : The Matrix | |
! double complex evala(d) (out) : eigenvalues | 1099 | 1107 | ! double complex evala(d) (out) : eigenvalues | |
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1100 | 1108 | ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer (out) : status =0 if something went wrong | 1101 | 1109 | ! integer (out) : status =0 if something went wrong | |
! | 1102 | 1110 | ! | |
! interfacing Lapack routine DGEEV | 1103 | 1111 | ! interfacing Lapack routine DGEEV | |
implicit none | 1104 | 1112 | implicit none | |
integer, intent(in) :: d | 1105 | 1113 | integer, intent(in) :: d | |
double precision, intent(in) :: a(d,d) | 1106 | 1114 | double precision, intent(in) :: a(d,d) | |
double complex, intent(out) :: evala(d) | 1107 | 1115 | double complex, intent(out) :: evala(d) | |
double complex, intent(out) :: eveca(d,d) | 1108 | 1116 | double complex, intent(out) :: eveca(d,d) | |
integer, intent(out), optional :: status | 1109 | 1117 | integer, intent(out), optional :: status | |
1110 | 1118 | |||
double precision, allocatable :: wc_a(:,:) ! a working copy of a | 1111 | 1119 | double precision, allocatable :: wc_a(:,:) ! a working copy of a | |
integer :: info | 1112 | 1120 | integer :: info | |
integer :: lwork | 1113 | 1121 | integer :: lwork | |
double precision, allocatable :: wr(:),wi(:) | 1114 | 1122 | double precision, allocatable :: wr(:),wi(:) | |
double precision :: vl ! unused but necessary for the call | 1115 | 1123 | double precision :: vl ! unused but necessary for the call | |
double precision, allocatable :: vr(:,:) | 1116 | 1124 | double precision, allocatable :: vr(:,:) | |
double precision, allocatable :: work(:) | 1117 | 1125 | double precision, allocatable :: work(:) | |
double precision :: twork(1) | 1118 | 1126 | double precision :: twork(1) | |
integer i | 1119 | 1127 | integer i | |
integer j | 1120 | 1128 | integer j | |
1121 | 1129 | |||
if (present(status)) status=1 | 1122 | 1130 | if (present(status)) status=1 | |
1123 | 1131 | |||
! making a working copy of a | 1124 | 1132 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1125 | 1133 | allocate(wc_a(d,d)) | |
!call dcopy(d*d,a,1,wc_a,1) | 1126 | 1134 | !call dcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1127 | 1135 | wc_a(:,:)=a(:,:) | |
1128 | 1136 | |||
allocate(wr(d)) | 1129 | 1137 | allocate(wr(d)) | |
allocate(wi(d)) | 1130 | 1138 | allocate(wi(d)) | |
allocate(vr(d,d)) | 1131 | 1139 | allocate(vr(d,d)) | |
! query optimal work size | 1132 | 1140 | ! query optimal work size | |
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | 1133 | 1141 | call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) | |
lwork=int(twork(1)) | 1134 | 1142 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1135 | 1143 | allocate(work(lwork)) | |
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | 1136 | 1144 | call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) | |
1137 | 1145 | |||
if (info /= 0) then | 1138 | 1146 | if (info /= 0) then | |
if (present(status)) status=0 | 1139 | 1147 | if (present(status)) status=0 | |
deallocate(work) | 1140 | 1148 | deallocate(work) | |
deallocate(vr) | 1141 | 1149 | deallocate(vr) | |
deallocate(wi) | 1142 | 1150 | deallocate(wi) | |
deallocate(wr) | 1143 | 1151 | deallocate(wr) | |
deallocate(wc_a) | 1144 | 1152 | deallocate(wc_a) | |
return | 1145 | 1153 | return | |
end if | 1146 | 1154 | end if | |
1147 | 1155 | |||
! now fill in the results | 1148 | 1156 | ! now fill in the results | |
i=1 | 1149 | 1157 | i=1 | |
do while(i<=d) | 1150 | 1158 | do while(i<=d) | |
evala(i)=dcmplx(wr(i),wi(i)) | 1151 | 1159 | evala(i)=dcmplx(wr(i),wi(i)) | |
if (wi(i) == 0.) then ! eigenvalue is real | 1152 | 1160 | if (wi(i) == 0.) then ! eigenvalue is real | |
eveca(:,i)=dcmplx(vr(:,i),0.) | 1153 | 1161 | eveca(:,i)=dcmplx(vr(:,i),0.) | |
else ! eigenvalue is complex | 1154 | 1162 | else ! eigenvalue is complex | |
evala(i+1)=dcmplx(wr(i+1),wi(i+1)) | 1155 | 1163 | evala(i+1)=dcmplx(wr(i+1),wi(i+1)) | |
eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1)) | 1156 | 1164 | eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1)) | |
eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1)) | 1157 | 1165 | eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1)) | |
i=i+1 | 1158 | 1166 | i=i+1 | |
end if | 1159 | 1167 | end if | |
i=i+1 | 1160 | 1168 | i=i+1 | |
enddo | 1161 | 1169 | enddo | |
1162 | 1170 | |||
deallocate(work) | 1163 | 1171 | deallocate(work) | |
deallocate(vr) | 1164 | 1172 | deallocate(vr) | |
deallocate(wi) | 1165 | 1173 | deallocate(wi) | |
deallocate(wr) | 1166 | 1174 | deallocate(wr) | |
deallocate(wc_a) | 1167 | 1175 | deallocate(wc_a) | |
1168 | 1176 | |||
end subroutine | 1169 | 1177 | end subroutine | |
1170 | 1178 | |||
subroutine fvn_c_matev(d,a,evala,eveca,status) | 1171 | 1179 | subroutine fvn_c_matev(d,a,evala,eveca,status) | |
! | 1172 | 1180 | ! | |
! integer d (in) : matrice rank | 1173 | 1181 | ! integer d (in) : matrice rank | |
! complex a(d,d) (in) : The Matrix | 1174 | 1182 | ! complex a(d,d) (in) : The Matrix | |
! complex evala(d) (out) : eigenvalues | 1175 | 1183 | ! complex evala(d) (out) : eigenvalues | |
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1176 | 1184 | ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer (out) : status =0 if something went wrong | 1177 | 1185 | ! integer (out) : status =0 if something went wrong | |
! | 1178 | 1186 | ! | |
! interfacing Lapack routine CGEEV | 1179 | 1187 | ! interfacing Lapack routine CGEEV | |
implicit none | 1180 | 1188 | implicit none | |
integer, intent(in) :: d | 1181 | 1189 | integer, intent(in) :: d | |
complex, intent(in) :: a(d,d) | 1182 | 1190 | complex, intent(in) :: a(d,d) | |
complex, intent(out) :: evala(d) | 1183 | 1191 | complex, intent(out) :: evala(d) | |
complex, intent(out) :: eveca(d,d) | 1184 | 1192 | complex, intent(out) :: eveca(d,d) | |
integer, intent(out), optional :: status | 1185 | 1193 | integer, intent(out), optional :: status | |
1186 | 1194 | |||
complex, allocatable :: wc_a(:,:) ! a working copy of a | 1187 | 1195 | complex, allocatable :: wc_a(:,:) ! a working copy of a | |
integer :: info | 1188 | 1196 | integer :: info | |
integer :: lwork | 1189 | 1197 | integer :: lwork | |
complex, allocatable :: work(:) | 1190 | 1198 | complex, allocatable :: work(:) | |
complex :: twork(1) | 1191 | 1199 | complex :: twork(1) | |
real, allocatable :: rwork(:) | 1192 | 1200 | real, allocatable :: rwork(:) | |
complex :: vl ! unused but necessary for the call | 1193 | 1201 | complex :: vl ! unused but necessary for the call | |
1194 | 1202 | |||
if (present(status)) status=1 | 1195 | 1203 | if (present(status)) status=1 | |
1196 | 1204 | |||
! making a working copy of a | 1197 | 1205 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1198 | 1206 | allocate(wc_a(d,d)) | |
!call ccopy(d*d,a,1,wc_a,1) | 1199 | 1207 | !call ccopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1200 | 1208 | wc_a(:,:)=a(:,:) | |
1201 | 1209 | |||
1202 | 1210 | |||
! query optimal work size | 1203 | 1211 | ! query optimal work size | |
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | 1204 | 1212 | call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | |
lwork=int(twork(1)) | 1205 | 1213 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1206 | 1214 | allocate(work(lwork)) | |
allocate(rwork(2*d)) | 1207 | 1215 | allocate(rwork(2*d)) | |
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | 1208 | 1216 | call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | |
1209 | 1217 | |||
if (info /= 0) then | 1210 | 1218 | if (info /= 0) then | |
if (present(status)) status=0 | 1211 | 1219 | if (present(status)) status=0 | |
end if | 1212 | 1220 | end if | |
deallocate(rwork) | 1213 | 1221 | deallocate(rwork) | |
deallocate(work) | 1214 | 1222 | deallocate(work) | |
deallocate(wc_a) | 1215 | 1223 | deallocate(wc_a) | |
1216 | 1224 | |||
end subroutine | 1217 | 1225 | end subroutine | |
1218 | 1226 | |||
subroutine fvn_z_matev(d,a,evala,eveca,status) | 1219 | 1227 | subroutine fvn_z_matev(d,a,evala,eveca,status) | |
! | 1220 | 1228 | ! | |
! integer d (in) : matrice rank | 1221 | 1229 | ! integer d (in) : matrice rank | |
! double complex a(d,d) (in) : The Matrix | 1222 | 1230 | ! double complex a(d,d) (in) : The Matrix | |
! double complex evala(d) (out) : eigenvalues | 1223 | 1231 | ! double complex evala(d) (out) : eigenvalues | |
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | 1224 | 1232 | ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector | |
! integer (out) : status =0 if something went wrong | 1225 | 1233 | ! integer (out) : status =0 if something went wrong | |
! | 1226 | 1234 | ! | |
! interfacing Lapack routine ZGEEV | 1227 | 1235 | ! interfacing Lapack routine ZGEEV | |
implicit none | 1228 | 1236 | implicit none | |
integer, intent(in) :: d | 1229 | 1237 | integer, intent(in) :: d | |
double complex, intent(in) :: a(d,d) | 1230 | 1238 | double complex, intent(in) :: a(d,d) | |
double complex, intent(out) :: evala(d) | 1231 | 1239 | double complex, intent(out) :: evala(d) | |
double complex, intent(out) :: eveca(d,d) | 1232 | 1240 | double complex, intent(out) :: eveca(d,d) | |
integer, intent(out), optional :: status | 1233 | 1241 | integer, intent(out), optional :: status | |
1234 | 1242 | |||
double complex, allocatable :: wc_a(:,:) ! a working copy of a | 1235 | 1243 | double complex, allocatable :: wc_a(:,:) ! a working copy of a | |
integer :: info | 1236 | 1244 | integer :: info | |
integer :: lwork | 1237 | 1245 | integer :: lwork | |
double complex, allocatable :: work(:) | 1238 | 1246 | double complex, allocatable :: work(:) | |
double complex :: twork(1) | 1239 | 1247 | double complex :: twork(1) | |
double precision, allocatable :: rwork(:) | 1240 | 1248 | double precision, allocatable :: rwork(:) | |
double complex :: vl ! unused but necessary for the call | 1241 | 1249 | double complex :: vl ! unused but necessary for the call | |
1242 | 1250 | |||
if (present(status)) status=1 | 1243 | 1251 | if (present(status)) status=1 | |
1244 | 1252 | |||
! making a working copy of a | 1245 | 1253 | ! making a working copy of a | |
allocate(wc_a(d,d)) | 1246 | 1254 | allocate(wc_a(d,d)) | |
!call zcopy(d*d,a,1,wc_a,1) | 1247 | 1255 | !call zcopy(d*d,a,1,wc_a,1) | |
wc_a(:,:)=a(:,:) | 1248 | 1256 | wc_a(:,:)=a(:,:) | |
1249 | 1257 | |||
! query optimal work size | 1250 | 1258 | ! query optimal work size | |
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | 1251 | 1259 | call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) | |
lwork=int(twork(1)) | 1252 | 1260 | lwork=int(twork(1)) | |
allocate(work(lwork)) | 1253 | 1261 | allocate(work(lwork)) | |
allocate(rwork(2*d)) | 1254 | 1262 | allocate(rwork(2*d)) | |
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | 1255 | 1263 | call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) | |
1256 | 1264 | |||
if (info /= 0) then | 1257 | 1265 | if (info /= 0) then | |
if (present(status)) status=0 | 1258 | 1266 | if (present(status)) status=0 | |
end if | 1259 | 1267 | end if | |
deallocate(rwork) | 1260 | 1268 | deallocate(rwork) | |
deallocate(work) | 1261 | 1269 | deallocate(work) | |
deallocate(wc_a) | 1262 | 1270 | deallocate(wc_a) | |
1263 | 1271 | |||
end subroutine | 1264 | 1272 | end subroutine | |
1265 | 1273 | |||
1266 | 1274 | |||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1267 | 1275 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 1268 | 1276 | ! | |
! Least square problem | 1269 | 1277 | ! Least square problem | |
! | 1270 | 1278 | ! | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | 1271 | 1279 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
! | 1272 | 1280 | ! | |
! | 1273 | 1281 | ! | |
1274 | 1282 | |||
1275 | 1283 | |||
1276 | 1284 | |||
1277 | 1285 | |||
subroutine fvn_d_lspoly(np,x,y,deg,coeff,status) | 1278 | 1286 | subroutine fvn_d_lspoly(np,x,y,deg,coeff,status) | |
! | 1279 | 1287 | ! | |
! Least square polynomial fitting | 1280 | 1288 | ! Least square polynomial fitting | |
! | 1281 | 1289 | ! | |
! Find the coefficients of the least square polynomial of a given degree | 1282 | 1290 | ! Find the coefficients of the least square polynomial of a given degree | |
! for a set of coordinates. | 1283 | 1291 | ! for a set of coordinates. | |
! | 1284 | 1292 | ! | |
! The degree must be lower than the number of points | 1285 | 1293 | ! The degree must be lower than the number of points | |
! | 1286 | 1294 | ! | |
! np (in) : number of points | 1287 | 1295 | ! np (in) : number of points | |
! x(np) (in) : x data | 1288 | 1296 | ! x(np) (in) : x data | |
! y(np) (in) : y data | 1289 | 1297 | ! y(np) (in) : y data | |
! deg (in) : polynomial's degree | 1290 | 1298 | ! deg (in) : polynomial's degree | |
! coeff(deg+1) (out) : polynomial coefficients | 1291 | 1299 | ! coeff(deg+1) (out) : polynomial coefficients | |
! status (out) : =0 if a problem occurs | 1292 | 1300 | ! status (out) : =0 if a problem occurs | |
! | 1293 | 1301 | ! | |
implicit none | 1294 | 1302 | implicit none | |
1295 | 1303 | |||
integer, intent(in) :: np,deg | 1296 | 1304 | integer, intent(in) :: np,deg | |
real(kind=8), intent(in), dimension(np) :: x,y | 1297 | 1305 | real(kind=8), intent(in), dimension(np) :: x,y | |
real(kind=8), intent(out), dimension(deg+1) :: coeff | 1298 | 1306 | real(kind=8), intent(out), dimension(deg+1) :: coeff | |
integer, intent(out), optional :: status | 1299 | 1307 | integer, intent(out), optional :: status | |
1300 | 1308 | |||
real(kind=8), allocatable, dimension(:,:) :: mat,bmat | 1301 | 1309 | real(kind=8), allocatable, dimension(:,:) :: mat,bmat | |
real(kind=8),dimension(:),allocatable :: work | 1302 | 1310 | real(kind=8),dimension(:),allocatable :: work |