Hi I’m using f2py to wrap the lapack routine dgesvd, by compiling the dgesvd.f file and linking it against llapack, as explained here
according to the docstring, the dgesvd module has the signature:
dgesvd - Function signature:
dgesvd(jobu,jobvt,m,n,a,s,u,vt,work,lwork,info,[lda,ldu,ldvt])
Required arguments:
jobu : input string(len=1)
jobvt : input string(len=1)
m : input int
n : input int
a : input rank-2 array('d') with bounds (lda,*)
s : input rank-1 array('d') with bounds (*)
u : input rank-2 array('d') with bounds (ldu,*)
vt : input rank-2 array('d') with bounds (ldvt,*)
work : input rank-1 array('d') with bounds (*)
lwork : input int
info : input int
Optional arguments:
lda := shape(a,0) input int
ldu := shape(u,0) input int
ldvt := shape(vt,0) input int
Then I use the following ocde to call the module:
mat = rand(20,30)
out_u,out_s,out_vh = zeros((20,20)), zeros((20,)), zeros((30,30))
rows, cols = shape(mat)
workspace = zeros((rows*cols))
out_info = 0
dgesvd(jobu='S',
jobvt='S',
m=rows,
n=cols,
a=mat,
s=out_s,
u=out_u,
vt=out_vh,
work=workspace,
lwork=rows*cols,
info=out_info)
Which gives me the correct singular values stored in out_s, but the matrices out_u and out_vh are still only filled with zeros, do I have to do something differently to get the left/right singular vectors as well ?
The code runs through, without any error, which means that out_info is 0.
(The argument ‘S’ for jobu and jobvt tells the routine to compute only the first min(m,n) singular vectors. Changing it to ‘A’, does not make any difference)
Any Ideas are highly appreciated!
Thanks
Mischa
f2pycreates python wrappers to Fortran code, but the python functions that are created are not intended to be called exactly like Fortran code. In Fortran, it is common practice to pass the output variables as an argument to the subroutine. This is not “pythonic”; besides, python doesn’t really support subroutines in the same way as Fortran. For this reason,f2pyturns your Fortran subroutine into a python function, and thus all output variables are returned by the function, not included in the call signature. So, you would have to call the function this way:However, the LAPACK routine is written in FORTRAN77, so it does not have any
INTENTdeclarations for the input/output variables.f2pyuses theINTENTdeclarations to figure out which variables are used as input, and which are to be returned as output. Based on the function signature that you posted,f2pyhas assumed that all variables are input, which is not what you want. For this reason, I recommend writing your own Fortran 90 wrapper routine that callsdgesvd, so that you can addINTENTdeclarations yourself to givef2pysome hints. I personally would also use the wrapper to allocate the work array to pass todgesvdso that you don’t have to pass it in from python. Exactly howf2pydetermines the input/output signature is explained here (there are three ways to do it, I prefer the third).