On Sat, May 04, 2019 at 06:42:47PM +0200, Thomas K?nig wrote:> > > - figure out Fortran2003 specification for C/Fortran interoperability > > -- this _sounds_ like the right solution, but I don't think many > > understand how to use it and what is implied (in particular, will > > it require making changes to LAPACK itself?) > > That would actually be fairly easy. If you declare the subroutines > BIND(C), as in > > subroutine foo(a,b) BIND(C,name="foo_") > real a > character*1 b > end > > you will get the calling signature that you already have in your C > sources. > > This also has the advantage of being standards compliant, and would be > probably be the preferred method. >With the caveat that one may need to use the VALUE attribute to account for pass-by-value vs pass-by-reference. -- Steve
Hi Steve,> With the caveat that one may need to use the VALUE attribute to > account for pass-by-value vs pass-by-reference.LAPACK should be all pass by reference, it is old F77-style code (except that the odd ALLOCATABLE array has snuck in in the testing routines).
On 5/4/19 6:49 PM, Steve Kargl wrote:> On Sat, May 04, 2019 at 06:42:47PM +0200, Thomas K?nig wrote: >>> - figure out Fortran2003 specification for C/Fortran interoperability >>> -- this _sounds_ like the right solution, but I don't think many >>> understand how to use it and what is implied (in particular, will >>> it require making changes to LAPACK itself?) >> That would actually be fairly easy. If you declare the subroutines >> BIND(C), as in >> >> subroutine foo(a,b) BIND(C,name="foo_") >> real a >> character*1 b >> end >> >> you will get the calling signature that you already have in your C >> sources. >> >> This also has the advantage of being standards compliant, and would be >> probably be the preferred method. >> > With the caveat that one may need to use the VALUE attribute to > account for pass-by-value vs pass-by-reference.This seems clean solution, but as I said before not easy, because currently the tradition is to call the Fortran interface directly from C (not via any C wrappers). This means one could not substitute LAPACK/BLAS at dynamic linking time, unless all LAPACK/BLAS implementations agreed on such a C interface. Now the substitution is based on the original Fortran interface. In case of R, if we only used the included reference BLAS/LAPACK, we could do this, define our wrappers, say "c_dgemm" for "dgemm", change R to call via that interface, ask maintainers of all packages to change their code to call via their interface, and this should work with all Fortran 2003 compilers. But, R is often used also with optimized BLAS/LAPACK implementations that can be substituted at dynamic linking time. And there we could do nothing at R level to help: we cannot generate such wrappers for an existing LAPACK/BLAS implementation (we don't have the source code, the compiler, etc). It would be certainly a good thing if BLAS/LAPACK, with all implementation and uses, switched to a way that is compliant with current Fortran standard. But this should best start with the reference BLAS/LAPACK, continue with other BLAS/LAPACK implementations, and then with systems using those libraries, including R and its packages. Unless/before this happens, it would really be great if we could still use gfortran to build and use this fundamental software library. Best Tomas
On Mon, May 6, 2019 at 11:55 AM Tomas Kalibera <tomas.kalibera at gmail.com> wrote:> > On 5/4/19 6:49 PM, Steve Kargl wrote: > > On Sat, May 04, 2019 at 06:42:47PM +0200, Thomas K?nig wrote: > >>> - figure out Fortran2003 specification for C/Fortran interoperability > >>> -- this _sounds_ like the right solution, but I don't think many > >>> understand how to use it and what is implied (in particular, will > >>> it require making changes to LAPACK itself?) > >> That would actually be fairly easy. If you declare the subroutines > >> BIND(C), as in > >> > >> subroutine foo(a,b) BIND(C,name="foo_") > >> real a > >> character*1 b > >> end > >> > >> you will get the calling signature that you already have in your C > >> sources. > >> > >> This also has the advantage of being standards compliant, and would be > >> probably be the preferred method. > >> > > With the caveat that one may need to use the VALUE attribute to > > account for pass-by-value vs pass-by-reference. > > This seems clean solution, but as I said before not easy, because > currently the tradition is to call the Fortran interface directly from C > (not via any C wrappers). This means one could not substitute > LAPACK/BLAS at dynamic linking time, unless all LAPACK/BLAS > implementations agreed on such a C interface. Now the substitution is > based on the original Fortran interface. > > In case of R, if we only used the included reference BLAS/LAPACK, we > could do this, define our wrappers, say "c_dgemm" for "dgemm", change R > to call via that interface, ask maintainers of all packages to change > their code to call via their interface, and this should work with all > Fortran 2003 compilers. > > But, R is often used also with optimized BLAS/LAPACK implementations > that can be substituted at dynamic linking time. And there we could do > nothing at R level to help: we cannot generate such wrappers for an > existing LAPACK/BLAS implementation (we don't have the source code, the > compiler, etc). > > It would be certainly a good thing if BLAS/LAPACK, with all > implementation and uses, switched to a way that is compliant with > current Fortran standard. But this should best start with the reference > BLAS/LAPACK, continue with other BLAS/LAPACK implementations, and then > with systems using those libraries, including R and its packages. > Unless/before this happens, it would really be great if we could still > use gfortran to build and use this fundamental software library.Hi, I don't think modifying your own builtin LAPACK makes sense, as you mention that would make R incompatible with another LAPACK provided by the system. And modifying LAPACK upstream by adding BIND(C) wouldn't work either, as that would break all the existing Fortran code calling LAPACK (as LAPACK is F77-style implicit interfaces, the Fortran caller has no knowledge of the interface and thus it must match the compiler default Fortran ABI). So the remaining place where this could be fixed would be in your C prototypes for LAPACK functions, so that they match what LAPACK expects. Arguably that's the correct approach anyway. I suppose for this task extending the GFortran -fc-prototypes option to generate C prototypes for external functions as well would help? AFAICS, this interface mismatch problem affects other Fortran compilers as well, just that by sheer luck this has worked mostly so far (that is, other Fortran compilers also expect a hidden string length argument, with no exception for length==1 strings). But with increasingly sophisticated interprocedural optimizations such sins can no longer be forgiven. -- Janne Blomqvist
Hi, gfortran trunk and 9-branch now have an option to automatically generate C prototypes for old-style F77 procedures. I just did for a in *.f; do gfortran -fsyntax-only -fc-prototypes-external $a > ${a%.f}.h; done in the src/modules/lapack directory. This generates header files which contain prototypes like int ilaenv_ (int *ispec, char *name, char *opts, int *n1, int *n2, int *n3, int *n4, size_t name_len, size_t opts_len); void dlacn2_ (int *n, double *v, double *x, int *isgn, double *est, int *kase, int *isave); void dlaln2_ (int_least32_t *ltrans, int *na, int *nw, double *smin, double *ca, double *a, int *lda, double *d1, double *d2, double *b, int *ldb, double *wr, double *wi, double *x, int *ldx, double *scale, double *xnorm, int *info); void dlabad_ (double *small, double *large); void drscl_ (int *n, double *sa, double *sx, int *incx); void dlatrs_ (char *uplo, char *trans, char *diag, char *normin, int *n, double *a, int *lda, double *x, double *scale, double *cnorm, int *info, size_t uplo_len, size_t trans_len, size_t diag_len, size_t normin_len); which could serve as the basis for adjusting the calling sequence for the C bindings to what the compiler expects. I checked, and it appears that at least ifort uses the same convention as gfortran 8/9 regarding character argument passing. Regards Thomas