Commit b85eed0171def3a9c57818323d3494afee5fc0ed

Authored by wdaniau
1 parent 19e954a45e

Added sorting of eigenvalues and vectors using an insertion sort algo to better

match imsl behavior

git-svn-id: https://lxsd.femto-st.fr/svn/fvn@52 b657c933-2333-4658-acf2-d3c7c2708721

Showing 1 changed file with 73 additions and 0 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 !
! 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(4),dimension(:,:),intent(in) :: a 222 222 real(4),dimension(:,:),intent(in) :: a
real(4),dimension(size(a,1),size(a,1)) :: fvn_op_s_matinv,tmp_array 223 223 real(4),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(8),dimension(:,:),intent(in) :: a 229 229 real(8),dimension(:,:),intent(in) :: a
real(8),dimension(size(a,1),size(a,1)) :: fvn_op_d_matinv,tmp_array 230 230 real(8),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(4),dimension(:,:),intent(in) :: a 236 236 complex(4),dimension(:,:),intent(in) :: a
complex(4),dimension(size(a,1),size(a,1)) :: fvn_op_c_matinv,tmp_array 237 237 complex(4),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(8),dimension(:,:),intent(in) :: a 243 243 complex(8),dimension(:,:),intent(in) :: a
complex(8),dimension(size(a,1),size(a,1)) :: fvn_op_z_matinv,tmp_array 244 244 complex(8),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(4), dimension(:,:), intent(in) :: a,b 254 254 real(4), dimension(:,:), intent(in) :: a,b
real(4), dimension(size(a,1),size(b,2)) :: fvn_op_s_ix 255 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) 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(8), dimension(:,:), intent(in) :: a,b 260 260 real(8), dimension(:,:), intent(in) :: a,b
real(8), dimension(size(a,1),size(b,2)) :: fvn_op_d_ix 261 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) 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(4), dimension(:,:), intent(in) :: a,b 266 266 complex(4), dimension(:,:), intent(in) :: a,b
complex(4), dimension(size(a,1),size(b,2)) :: fvn_op_c_ix 267 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) 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(8), dimension(:,:), intent(in) :: a,b 272 272 complex(8), dimension(:,:), intent(in) :: a,b
complex(8), dimension(size(a,1),size(b,2)) :: fvn_op_z_ix 273 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) 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(4), dimension(:,:), intent(in) :: a,b 282 282 real(4), dimension(:,:), intent(in) :: a,b
real(4), dimension(size(a,1),size(b,2)) :: fvn_op_s_xi 283 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)) 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(8), dimension(:,:), intent(in) :: a,b 288 288 real(8), dimension(:,:), intent(in) :: a,b
real(8), dimension(size(a,1),size(b,2)) :: fvn_op_d_xi 289 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)) 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(4), dimension(:,:), intent(in) :: a,b 294 294 complex(4), dimension(:,:), intent(in) :: a,b
complex(4), dimension(size(a,1),size(b,2)) :: fvn_op_c_xi 295 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)) 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(8), dimension(:,:), intent(in) :: a,b 300 300 complex(8), dimension(:,:), intent(in) :: a,b
complex(8), dimension(size(a,1),size(b,2)) :: fvn_op_z_xi 301 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)) 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(4),dimension(:,:),intent(in) :: a 310 310 complex(4),dimension(:,:),intent(in) :: a
complex(4),dimension(size(a,2),size(a,1)) :: fvn_op_c_conj_transpose 311 311 complex(4),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(8),dimension(:,:),intent(in) :: a 316 316 complex(8),dimension(:,:),intent(in) :: a
complex(8),dimension(size(a,2),size(a,1)) :: fvn_op_z_conj_transpose 317 317 complex(8),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(4), dimension(:,:), intent(in) :: a,b 327 327 complex(4), dimension(:,:), intent(in) :: a,b
complex(4), dimension(size(a,2),size(b,2)) :: fvn_op_c_hx 328 328 complex(4), 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(8), dimension(:,:), intent(in) :: a,b 333 333 complex(8), dimension(:,:), intent(in) :: a,b
complex(8), dimension(size(a,2),size(b,2)) :: fvn_op_z_hx 334 334 complex(8), 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(4), dimension(:,:), intent(in) :: a,b 344 344 complex(4), dimension(:,:), intent(in) :: a,b
complex(4), dimension(size(a,1),size(b,1)) :: fvn_op_c_xh 345 345 complex(4), 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(8), dimension(:,:), intent(in) :: a,b 350 350 complex(8), dimension(:,:), intent(in) :: a,b
complex(8), dimension(size(a,1),size(b,1)) :: fvn_op_z_xh 351 351 complex(8), 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=4) :: n 366 366 integer(kind=4) :: n
real(kind=8), dimension(n,n) :: fvn_d_ident 367 367 real(kind=8), dimension(n,n) :: fvn_d_ident
368 368
real(kind=8),dimension(n*n) :: vect 369 369 real(kind=8),dimension(n*n) :: vect
integer(kind=4) :: i 370 370 integer(kind=4) :: i
371 371
vect=0._8 372 372 vect=0._8
vect(1:n*n:n+1) = 1._8 373 373 vect(1:n*n:n+1) = 1._8
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=4) :: n 379 379 integer(kind=4) :: n
real(kind=4), dimension(n,n) :: fvn_s_ident 380 380 real(kind=4), dimension(n,n) :: fvn_s_ident
381 381
real(kind=4),dimension(n*n) :: vect 382 382 real(kind=4),dimension(n*n) :: vect
integer(kind=4) :: i 383 383 integer(kind=4) :: i
384 384
vect=0._4 385 385 vect=0._4
vect(1:n*n:n+1) = 1._4 386 386 vect(1:n*n:n+1) = 1._4
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=4) :: n 392 392 integer(kind=4) :: n
complex(kind=4), dimension(n,n) :: fvn_c_ident 393 393 complex(kind=4), dimension(n,n) :: fvn_c_ident
394 394
complex(kind=4),dimension(n*n) :: vect 395 395 complex(kind=4),dimension(n*n) :: vect
integer(kind=4) :: i 396 396 integer(kind=4) :: i
397 397
vect=(0._4,0._4) 398 398 vect=(0._4,0._4)
vect(1:n*n:n+1) = (1._4,0._4) 399 399 vect(1:n*n:n+1) = (1._4,0._4)
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=4) :: n 405 405 integer(kind=4) :: n
complex(kind=8), dimension(n,n) :: fvn_z_ident 406 406 complex(kind=8), dimension(n,n) :: fvn_z_ident
407 407
complex(kind=8),dimension(n*n) :: vect 408 408 complex(kind=8),dimension(n*n) :: vect
integer(kind=4) :: i 409 409 integer(kind=4) :: i
410 410
vect=(0._8,0._8) 411 411 vect=(0._8,0._8)
vect(1:n*n:n+1) = (1._8,0._8) 412 412 vect(1:n*n:n+1) = (1._8,0._8)
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 matrix using BLAS and LAPACK 426 426 ! Matrix inversion of a real 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, intent(in) :: d 434 434 integer, intent(in) :: d
real, intent(in) :: a(d,d) 435 435 real, intent(in) :: a(d,d)
real, intent(out) :: inva(d,d) 436 436 real, intent(out) :: inva(d,d)
integer, intent(out),optional :: status 437 437 integer, intent(out),optional :: status
438 438
integer, allocatable :: ipiv(:) 439 439 integer, allocatable :: ipiv(:)
real, allocatable :: work(:) 440 440 real, allocatable :: work(:)
real twork(1) 441 441 real twork(1)
integer :: info 442 442 integer :: info
integer :: lwork 443 443 integer :: 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 double precision matrix using BLAS and LAPACK 475 475 ! Matrix inversion of a double precision 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, intent(in) :: d 483 483 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 484 484 double precision, intent(in) :: a(d,d)
double precision, intent(out) :: inva(d,d) 485 485 double precision, intent(out) :: inva(d,d)
integer, intent(out),optional :: status 486 486 integer, intent(out),optional :: status
487 487
integer, allocatable :: ipiv(:) 488 488 integer, allocatable :: ipiv(:)
double precision, allocatable :: work(:) 489 489 double precision, allocatable :: work(:)
double precision :: twork(1) 490 490 double precision :: twork(1)
integer :: info 491 491 integer :: info
integer :: lwork 492 492 integer :: 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 matrix using BLAS and LAPACK 524 524 ! Matrix inversion of a complex 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, intent(in) :: d 532 532 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 533 533 complex, intent(in) :: a(d,d)
complex, intent(out) :: inva(d,d) 534 534 complex, intent(out) :: inva(d,d)
integer, intent(out),optional :: status 535 535 integer, intent(out),optional :: status
536 536
integer, allocatable :: ipiv(:) 537 537 integer, allocatable :: ipiv(:)
complex, allocatable :: work(:) 538 538 complex, allocatable :: work(:)
complex :: twork(1) 539 539 complex :: twork(1)
integer :: info 540 540 integer :: info
integer :: lwork 541 541 integer :: 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 double complex matrix using BLAS and LAPACK 574 574 ! Matrix inversion of a double complex 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, intent(in) :: d 582 582 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 583 583 double complex, intent(in) :: a(d,d)
double complex, intent(out) :: inva(d,d) 584 584 double complex, intent(out) :: inva(d,d)
integer, intent(out),optional :: status 585 585 integer, intent(out),optional :: status
586 586
integer, allocatable :: ipiv(:) 587 587 integer, allocatable :: ipiv(:)
double complex, allocatable :: work(:) 588 588 double complex, allocatable :: work(:)
double complex :: twork(1) 589 589 double complex :: twork(1)
integer :: info 590 590 integer :: info
integer :: lwork 591 591 integer :: 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, intent(in) :: d 637 637 integer, intent(in) :: d
real, intent(in) :: a(d,d) 638 638 real, intent(in) :: a(d,d)
integer, intent(out), optional :: status 639 639 integer, intent(out), optional :: status
real :: fvn_s_det 640 640 real :: fvn_s_det
641 641
real, allocatable :: wc_a(:,:) 642 642 real, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 643 643 integer, allocatable :: ipiv(:)
integer :: info,i 644 644 integer :: 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, intent(in) :: d 680 680 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 681 681 double precision, intent(in) :: a(d,d)
integer, intent(out), optional :: status 682 682 integer, intent(out), optional :: status
double precision :: fvn_d_det 683 683 double precision :: fvn_d_det
684 684
double precision, allocatable :: wc_a(:,:) 685 685 double precision, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 686 686 integer, allocatable :: ipiv(:)
integer :: info,i 687 687 integer :: 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, intent(in) :: d 722 722 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 723 723 complex, intent(in) :: a(d,d)
integer, intent(out), optional :: status 724 724 integer, intent(out), optional :: status
complex :: fvn_c_det 725 725 complex :: fvn_c_det
726 726
complex, allocatable :: wc_a(:,:) 727 727 complex, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 728 728 integer, allocatable :: ipiv(:)
integer :: info,i 729 729 integer :: 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, intent(in) :: d 766 766 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 767 767 double complex, intent(in) :: a(d,d)
integer, intent(out), optional :: status 768 768 integer, intent(out), optional :: status
double complex :: fvn_z_det 769 769 double complex :: fvn_z_det
770 770
double complex, allocatable :: wc_a(:,:) 771 771 double complex, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 772 772 integer, allocatable :: ipiv(:)
integer :: info,i 773 773 integer :: 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, intent(in) :: d 818 818 integer, intent(in) :: d
real, intent(in) :: a(d,d) 819 819 real, intent(in) :: a(d,d)
real, intent(out) :: rcond 820 820 real, intent(out) :: rcond
integer, intent(out), optional :: status 821 821 integer, intent(out), optional :: status
822 822
real, allocatable :: work(:) 823 823 real, allocatable :: work(:)
integer, allocatable :: iwork(:) 824 824 integer, allocatable :: iwork(:)
real :: anorm 825 825 real :: anorm
real, allocatable :: wc_a(:,:) ! working copy of a 826 826 real, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 827 827 integer :: info
integer, allocatable :: ipiv(:) 828 828 integer, allocatable :: ipiv(:)
829 829
real, external :: slange 830 830 real, 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, intent(in) :: d 871 871 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 872 872 double precision, intent(in) :: a(d,d)
double precision, intent(out) :: rcond 873 873 double precision, intent(out) :: rcond
integer, intent(out), optional :: status 874 874 integer, intent(out), optional :: status
875 875
double precision, allocatable :: work(:) 876 876 double precision, allocatable :: work(:)
integer, allocatable :: iwork(:) 877 877 integer, allocatable :: iwork(:)
double precision :: anorm 878 878 double precision :: anorm
double precision, allocatable :: wc_a(:,:) ! working copy of a 879 879 double precision, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 880 880 integer :: info
integer, allocatable :: ipiv(:) 881 881 integer, allocatable :: ipiv(:)
882 882
double precision, external :: dlange 883 883 double precision, 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, intent(in) :: d 925 925 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 926 926 complex, intent(in) :: a(d,d)
real, intent(out) :: rcond 927 927 real, intent(out) :: rcond
integer, intent(out), optional :: status 928 928 integer, intent(out), optional :: status
929 929
real, allocatable :: rwork(:) 930 930 real, allocatable :: rwork(:)
complex, allocatable :: work(:) 931 931 complex, allocatable :: work(:)
integer, allocatable :: iwork(:) 932 932 integer, allocatable :: iwork(:)
real :: anorm 933 933 real :: anorm
complex, allocatable :: wc_a(:,:) ! working copy of a 934 934 complex, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 935 935 integer :: info
integer, allocatable :: ipiv(:) 936 936 integer, allocatable :: ipiv(:)
937 937
real, external :: clange 938 938 real, 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, intent(in) :: d 978 978 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 979 979 double complex, intent(in) :: a(d,d)
double precision, intent(out) :: rcond 980 980 double precision, intent(out) :: rcond
integer, intent(out), optional :: status 981 981 integer, intent(out), optional :: status
982 982
double complex, allocatable :: work(:) 983 983 double complex, allocatable :: work(:)
double precision, allocatable :: rwork(:) 984 984 double precision, allocatable :: rwork(:)
double precision :: anorm 985 985 double precision :: anorm
double complex, allocatable :: wc_a(:,:) ! working copy of a 986 986 double complex, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 987 987 integer :: info
integer, allocatable :: ipiv(:) 988 988 integer, allocatable :: ipiv(:)
989 989
double precision, external :: zlange 990 990 double precision, 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
1028 ! August 2009
1029 ! William Daniau
1030 ! Adding sorting of eigenvalues and vectors
1031 subroutine fvn_z_sort_eigen(d,v,vec)
1032 ! this routine takes in input :
1033 ! v : a vector containing unsorted eigenvalues
1034 ! vec : a matrix where vec(:,j) is the eigenvector corresponding to v(j)
1035 !
1036 ! At the end of subroutine the eigenvalues are sorted by decreasing order of
1037 ! modulus so as the vectors.
1038 implicit none
1039 integer :: d,i,j
1040 complex(8),dimension(d) :: v
1041 complex(8),dimension(d,d) :: vec
1042 complex(8) :: cur_v
1043 complex(8), dimension(d) :: cur_vec
1044
1045 do i=2,d
1046 cur_v=v(i)
1047 cur_vec=vec(:,i)
1048 j=i-1
1049 do while( (j>=1) .and. (abs(v(j)) < abs(cur_v)) )
1050 v(j+1)=v(j)
1051 vec(:,j+1)=vec(:,j)
1052 j=j-1
1053 end do
1054 v(j+1)=cur_v
1055 vec(:,j+1)=cur_vec
1056 end do
1057
1058 end subroutine
1059
1060 subroutine fvn_c_sort_eigen(d,v,vec)
1061 ! this routine takes in input :
1062 ! v : a vector containing unsorted eigenvalues
1063 ! vec : a matrix where vec(:,j) is the eigenvector corresponding to v(j)
1064 !
1065 ! At the end of subroutine the eigenvalues are sorted by decreasing order of
1066 ! modulus so as the vectors.
1067 implicit none
1068 integer :: d,i,j
1069 complex(4),dimension(d) :: v
1070 complex(4),dimension(d,d) :: vec
1071 complex(4) :: cur_v
1072 complex(4), dimension(d) :: cur_vec
1073
1074 do i=2,d
1075 cur_v=v(i)
1076 cur_vec=vec(:,i)
1077 j=i-1
1078 do while( (j>=1) .and. (abs(v(j)) < abs(cur_v)) )
1079 v(j+1)=v(j)
1080 vec(:,j+1)=vec(:,j)
1081 j=j-1
1082 end do
1083 v(j+1)=cur_v
1084 vec(:,j+1)=cur_vec
1085 end do
1086
1087 end subroutine
1088
subroutine fvn_s_matev(d,a,evala,eveca,status) 1028 1089 subroutine fvn_s_matev(d,a,evala,eveca,status)
! 1029 1090 !
! integer d (in) : matrice rank 1030 1091 ! integer d (in) : matrice rank
! real a(d,d) (in) : The Matrix 1031 1092 ! real a(d,d) (in) : The Matrix
! complex evala(d) (out) : eigenvalues 1032 1093 ! complex evala(d) (out) : eigenvalues
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 1033 1094 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 1034 1095 ! integer (out) : status =0 if something went wrong
! 1035 1096 !
! interfacing Lapack routine SGEEV 1036 1097 ! interfacing Lapack routine SGEEV
implicit none 1037 1098 implicit none
integer, intent(in) :: d 1038 1099 integer, intent(in) :: d
real, intent(in) :: a(d,d) 1039 1100 real, intent(in) :: a(d,d)
complex, intent(out) :: evala(d) 1040 1101 complex, intent(out) :: evala(d)
complex, intent(out) :: eveca(d,d) 1041 1102 complex, intent(out) :: eveca(d,d)
integer, intent(out), optional :: status 1042 1103 integer, intent(out), optional :: status
1043 1104
real, allocatable :: wc_a(:,:) ! a working copy of a 1044 1105 real, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 1045 1106 integer :: info
integer :: lwork 1046 1107 integer :: lwork
real, allocatable :: wr(:),wi(:) 1047 1108 real, allocatable :: wr(:),wi(:)
real :: vl ! unused but necessary for the call 1048 1109 real :: vl ! unused but necessary for the call
real, allocatable :: vr(:,:) 1049 1110 real, allocatable :: vr(:,:)
real, allocatable :: work(:) 1050 1111 real, allocatable :: work(:)
real :: twork(1) 1051 1112 real :: twork(1)
integer i 1052 1113 integer i
integer j 1053 1114 integer j
1054 1115
if (present(status)) status=1 1055 1116 if (present(status)) status=1
1056 1117
! making a working copy of a 1057 1118 ! making a working copy of a
allocate(wc_a(d,d)) 1058 1119 allocate(wc_a(d,d))
!call scopy(d*d,a,1,wc_a,1) 1059 1120 !call scopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 1060 1121 wc_a(:,:)=a(:,:)
1061 1122
allocate(wr(d)) 1062 1123 allocate(wr(d))
allocate(wi(d)) 1063 1124 allocate(wi(d))
allocate(vr(d,d)) 1064 1125 allocate(vr(d,d))
! query optimal work size 1065 1126 ! query optimal work size
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) 1066 1127 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
lwork=int(twork(1)) 1067 1128 lwork=int(twork(1))
allocate(work(lwork)) 1068 1129 allocate(work(lwork))
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) 1069 1130 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
1070 1131
if (info /= 0) then 1071 1132 if (info /= 0) then
if (present(status)) status=0 1072 1133 if (present(status)) status=0
deallocate(work) 1073 1134 deallocate(work)
deallocate(vr) 1074 1135 deallocate(vr)
deallocate(wi) 1075 1136 deallocate(wi)
deallocate(wr) 1076 1137 deallocate(wr)
deallocate(wc_a) 1077 1138 deallocate(wc_a)
return 1078 1139 return
end if 1079 1140 end if
1080 1141
! now fill in the results 1081 1142 ! now fill in the results
i=1 1082 1143 i=1
do while(i<=d) 1083 1144 do while(i<=d)
evala(i)=cmplx(wr(i),wi(i)) 1084 1145 evala(i)=cmplx(wr(i),wi(i))
if (wi(i) == 0.) then ! eigenvalue is real 1085 1146 if (wi(i) == 0.) then ! eigenvalue is real
eveca(:,i)=cmplx(vr(:,i),0.) 1086 1147 eveca(:,i)=cmplx(vr(:,i),0.)
else ! eigenvalue is complex 1087 1148 else ! eigenvalue is complex
evala(i+1)=cmplx(wr(i+1),wi(i+1)) 1088 1149 evala(i+1)=cmplx(wr(i+1),wi(i+1))
eveca(:,i)=cmplx(vr(:,i),vr(:,i+1)) 1089 1150 eveca(:,i)=cmplx(vr(:,i),vr(:,i+1))
eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1)) 1090 1151 eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1))
i=i+1 1091 1152 i=i+1
end if 1092 1153 end if
i=i+1 1093 1154 i=i+1
enddo 1094 1155 enddo
deallocate(work) 1095 1156 deallocate(work)
deallocate(vr) 1096 1157 deallocate(vr)
deallocate(wi) 1097 1158 deallocate(wi)
deallocate(wr) 1098 1159 deallocate(wr)
deallocate(wc_a) 1099 1160 deallocate(wc_a)
1100 1161
1162 ! sorting
1163 call fvn_c_sort_eigen(d,evala,eveca)
1164
end subroutine 1101 1165 end subroutine
1102 1166
subroutine fvn_d_matev(d,a,evala,eveca,status) 1103 1167 subroutine fvn_d_matev(d,a,evala,eveca,status)
! 1104 1168 !
! integer d (in) : matrice rank 1105 1169 ! integer d (in) : matrice rank
! double precision a(d,d) (in) : The Matrix 1106 1170 ! double precision a(d,d) (in) : The Matrix
! double complex evala(d) (out) : eigenvalues 1107 1171 ! double complex evala(d) (out) : eigenvalues
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 1108 1172 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 1109 1173 ! integer (out) : status =0 if something went wrong
! 1110 1174 !
! interfacing Lapack routine DGEEV 1111 1175 ! interfacing Lapack routine DGEEV
implicit none 1112 1176 implicit none
integer, intent(in) :: d 1113 1177 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 1114 1178 double precision, intent(in) :: a(d,d)
double complex, intent(out) :: evala(d) 1115 1179 double complex, intent(out) :: evala(d)
double complex, intent(out) :: eveca(d,d) 1116 1180 double complex, intent(out) :: eveca(d,d)
integer, intent(out), optional :: status 1117 1181 integer, intent(out), optional :: status
1118 1182
double precision, allocatable :: wc_a(:,:) ! a working copy of a 1119 1183 double precision, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 1120 1184 integer :: info
integer :: lwork 1121 1185 integer :: lwork
double precision, allocatable :: wr(:),wi(:) 1122 1186 double precision, allocatable :: wr(:),wi(:)
double precision :: vl ! unused but necessary for the call 1123 1187 double precision :: vl ! unused but necessary for the call
double precision, allocatable :: vr(:,:) 1124 1188 double precision, allocatable :: vr(:,:)
double precision, allocatable :: work(:) 1125 1189 double precision, allocatable :: work(:)
double precision :: twork(1) 1126 1190 double precision :: twork(1)
integer i 1127 1191 integer i
integer j 1128 1192 integer j
1129 1193
if (present(status)) status=1 1130 1194 if (present(status)) status=1
1131 1195
! making a working copy of a 1132 1196 ! making a working copy of a
allocate(wc_a(d,d)) 1133 1197 allocate(wc_a(d,d))
!call dcopy(d*d,a,1,wc_a,1) 1134 1198 !call dcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 1135 1199 wc_a(:,:)=a(:,:)
1136 1200
allocate(wr(d)) 1137 1201 allocate(wr(d))
allocate(wi(d)) 1138 1202 allocate(wi(d))
allocate(vr(d,d)) 1139 1203 allocate(vr(d,d))
! query optimal work size 1140 1204 ! query optimal work size
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) 1141 1205 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
lwork=int(twork(1)) 1142 1206 lwork=int(twork(1))
allocate(work(lwork)) 1143 1207 allocate(work(lwork))
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) 1144 1208 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
1145 1209
if (info /= 0) then 1146 1210 if (info /= 0) then
if (present(status)) status=0 1147 1211 if (present(status)) status=0
deallocate(work) 1148 1212 deallocate(work)
deallocate(vr) 1149 1213 deallocate(vr)
deallocate(wi) 1150 1214 deallocate(wi)
deallocate(wr) 1151 1215 deallocate(wr)
deallocate(wc_a) 1152 1216 deallocate(wc_a)
return 1153 1217 return
end if 1154 1218 end if
1155 1219
! now fill in the results 1156 1220 ! now fill in the results
i=1 1157 1221 i=1
do while(i<=d) 1158 1222 do while(i<=d)
evala(i)=dcmplx(wr(i),wi(i)) 1159 1223 evala(i)=dcmplx(wr(i),wi(i))
if (wi(i) == 0.) then ! eigenvalue is real 1160 1224 if (wi(i) == 0.) then ! eigenvalue is real
eveca(:,i)=dcmplx(vr(:,i),0.) 1161 1225 eveca(:,i)=dcmplx(vr(:,i),0.)
else ! eigenvalue is complex 1162 1226 else ! eigenvalue is complex
evala(i+1)=dcmplx(wr(i+1),wi(i+1)) 1163 1227 evala(i+1)=dcmplx(wr(i+1),wi(i+1))
eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1)) 1164 1228 eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1))
eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1)) 1165 1229 eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1))
i=i+1 1166 1230 i=i+1
end if 1167 1231 end if
i=i+1 1168 1232 i=i+1
enddo 1169 1233 enddo
1170 1234
deallocate(work) 1171 1235 deallocate(work)
deallocate(vr) 1172 1236 deallocate(vr)
deallocate(wi) 1173 1237 deallocate(wi)
deallocate(wr) 1174 1238 deallocate(wr)
deallocate(wc_a) 1175 1239 deallocate(wc_a)
1176 1240
1241 ! sorting
1242 call fvn_z_sort_eigen(d,evala,eveca)
1243
end subroutine 1177 1244 end subroutine
1178 1245
subroutine fvn_c_matev(d,a,evala,eveca,status) 1179 1246 subroutine fvn_c_matev(d,a,evala,eveca,status)
! 1180 1247 !
! integer d (in) : matrice rank 1181 1248 ! integer d (in) : matrice rank
! complex a(d,d) (in) : The Matrix 1182 1249 ! complex a(d,d) (in) : The Matrix
! complex evala(d) (out) : eigenvalues 1183 1250 ! complex evala(d) (out) : eigenvalues
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 1184 1251 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 1185 1252 ! integer (out) : status =0 if something went wrong
! 1186 1253 !
! interfacing Lapack routine CGEEV 1187 1254 ! interfacing Lapack routine CGEEV
implicit none 1188 1255 implicit none
integer, intent(in) :: d 1189 1256 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 1190 1257 complex, intent(in) :: a(d,d)
complex, intent(out) :: evala(d) 1191 1258 complex, intent(out) :: evala(d)
complex, intent(out) :: eveca(d,d) 1192 1259 complex, intent(out) :: eveca(d,d)
integer, intent(out), optional :: status 1193 1260 integer, intent(out), optional :: status
1194 1261
complex, allocatable :: wc_a(:,:) ! a working copy of a 1195 1262 complex, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 1196 1263 integer :: info
integer :: lwork 1197 1264 integer :: lwork
complex, allocatable :: work(:) 1198 1265 complex, allocatable :: work(:)
complex :: twork(1) 1199 1266 complex :: twork(1)
real, allocatable :: rwork(:) 1200 1267 real, allocatable :: rwork(:)
complex :: vl ! unused but necessary for the call 1201 1268 complex :: vl ! unused but necessary for the call
1202 1269
if (present(status)) status=1 1203 1270 if (present(status)) status=1
1204 1271
! making a working copy of a 1205 1272 ! making a working copy of a
allocate(wc_a(d,d)) 1206 1273 allocate(wc_a(d,d))
!call ccopy(d*d,a,1,wc_a,1) 1207 1274 !call ccopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 1208 1275 wc_a(:,:)=a(:,:)
1209 1276
1210 1277
! query optimal work size 1211 1278 ! query optimal work size
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) 1212 1279 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
lwork=int(twork(1)) 1213 1280 lwork=int(twork(1))
allocate(work(lwork)) 1214 1281 allocate(work(lwork))
allocate(rwork(2*d)) 1215 1282 allocate(rwork(2*d))
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) 1216 1283 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
1217 1284
if (info /= 0) then 1218 1285 if (info /= 0) then
if (present(status)) status=0 1219 1286 if (present(status)) status=0
end if 1220 1287 end if
deallocate(rwork) 1221 1288 deallocate(rwork)
deallocate(work) 1222 1289 deallocate(work)
deallocate(wc_a) 1223 1290 deallocate(wc_a)
1224 1291
1292 ! sorting
1293 call fvn_c_sort_eigen(d,evala,eveca)
1294
end subroutine 1225 1295 end subroutine
1226 1296
subroutine fvn_z_matev(d,a,evala,eveca,status) 1227 1297 subroutine fvn_z_matev(d,a,evala,eveca,status)
! 1228 1298 !
! integer d (in) : matrice rank 1229 1299 ! integer d (in) : matrice rank
! double complex a(d,d) (in) : The Matrix 1230 1300 ! double complex a(d,d) (in) : The Matrix
! double complex evala(d) (out) : eigenvalues 1231 1301 ! double complex evala(d) (out) : eigenvalues
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 1232 1302 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 1233 1303 ! integer (out) : status =0 if something went wrong
! 1234 1304 !
! interfacing Lapack routine ZGEEV 1235 1305 ! interfacing Lapack routine ZGEEV
implicit none 1236 1306 implicit none
integer, intent(in) :: d 1237 1307 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 1238 1308 double complex, intent(in) :: a(d,d)
double complex, intent(out) :: evala(d) 1239 1309 double complex, intent(out) :: evala(d)
double complex, intent(out) :: eveca(d,d) 1240 1310 double complex, intent(out) :: eveca(d,d)
integer, intent(out), optional :: status 1241 1311 integer, intent(out), optional :: status
1242 1312
double complex, allocatable :: wc_a(:,:) ! a working copy of a 1243 1313 double complex, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 1244 1314 integer :: info
integer :: lwork 1245 1315 integer :: lwork
double complex, allocatable :: work(:) 1246 1316 double complex, allocatable :: work(:)
double complex :: twork(1) 1247 1317 double complex :: twork(1)
double precision, allocatable :: rwork(:) 1248 1318 double precision, allocatable :: rwork(:)
double complex :: vl ! unused but necessary for the call 1249 1319 double complex :: vl ! unused but necessary for the call
1250 1320
if (present(status)) status=1 1251 1321 if (present(status)) status=1
1252 1322
! making a working copy of a 1253 1323 ! making a working copy of a
allocate(wc_a(d,d)) 1254 1324 allocate(wc_a(d,d))
!call zcopy(d*d,a,1,wc_a,1) 1255 1325 !call zcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 1256 1326 wc_a(:,:)=a(:,:)
1257 1327
! query optimal work size 1258 1328 ! query optimal work size
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) 1259 1329 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
lwork=int(twork(1)) 1260 1330 lwork=int(twork(1))
allocate(work(lwork)) 1261 1331 allocate(work(lwork))
allocate(rwork(2*d)) 1262 1332 allocate(rwork(2*d))
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) 1263 1333 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
1264 1334
if (info /= 0) then 1265 1335 if (info /= 0) then
if (present(status)) status=0 1266 1336 if (present(status)) status=0
end if 1267 1337 end if
deallocate(rwork) 1268 1338 deallocate(rwork)
deallocate(work) 1269 1339 deallocate(work)
deallocate(wc_a) 1270 1340 deallocate(wc_a)
1341
1342 ! sorting
1343 call fvn_z_sort_eigen(d,evala,eveca)
1271 1344
end subroutine 1272 1345 end subroutine
1273 1346
1274 1347
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1275 1348 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1276 1349 !
! Least square problem 1277 1350 ! Least square problem
! 1278 1351 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1279 1352 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1280 1353 !
! 1281 1354 !
1282 1355
1283 1356
1284 1357
1285 1358
subroutine fvn_d_lspoly(np,x,y,deg,coeff,status) 1286 1359 subroutine fvn_d_lspoly(np,x,y,deg,coeff,status)
! 1287 1360 !
! Least square polynomial fitting 1288 1361 ! Least square polynomial fitting
! 1289 1362 !
! Find the coefficients of the least square polynomial of a given degree 1290 1363 ! Find the coefficients of the least square polynomial of a given degree
! for a set of coordinates. 1291 1364 ! for a set of coordinates.
! 1292 1365 !
! The degree must be lower than the number of points 1293 1366 ! The degree must be lower than the number of points
! 1294 1367 !
! np (in) : number of points 1295 1368 ! np (in) : number of points
! x(np) (in) : x data 1296 1369 ! x(np) (in) : x data
! y(np) (in) : y data 1297 1370 ! y(np) (in) : y data
! deg (in) : polynomial's degree 1298 1371 ! deg (in) : polynomial's degree
! coeff(deg+1) (out) : polynomial coefficients 1299 1372 ! coeff(deg+1) (out) : polynomial coefficients
! status (out) : =0 if a problem occurs 1300 1373 ! status (out) : =0 if a problem occurs
! 1301 1374 !
implicit none 1302 1375 implicit none