mirror of https://github.com/pyodide/pyodide.git
Fix scipy linking errors (#2289)
With newer versions of emscripten, linker errors surface eariler. This makes it easier to find function pointer cast errors without having to execute the bad code path -- the errors happen when the wasm modules are linked (at load time in the browser) Anyways, this fixes more linker errors. Mostly the problems have to do with LAPACK functions that take string arguments. Most LAPACK functions that take string arguments use them as enums and only care about the first character of the string. Because of the way that f2c works, we need to replace these strings with the ascii code of the first character so we should replace: sTRSV( 'UPPER', 'NOTRANS', 'NONUNIT', J, H, LDH, Y, 1 ) ==> CALL sTRSV( 85, 78, 78, J, H, LDH, Y, 1 ) where 85 and 78 are the ascii codes of U and N. Various character variables are subbed into being integer variables. The two functions `ilaenv` and `xerbla` expect actual C strings as an argument, but it is very annoying to produce C strings so instead I added wrapper functions ilaenvf2c and xerblaf2c to clapack and instead of calling ilaenv and xerbla we call the f2c versions.
This commit is contained in:
parent
f4f013a405
commit
e865b77040
|
@ -40,8 +40,8 @@ export PYODIDE=1
|
|||
# This is the legacy environment variable used for the aforementioned purpose
|
||||
export PYODIDE_PACKAGE_ABI=1
|
||||
|
||||
# export DBGFLAGS=-g3 -gseparate-dwarf -sSEPARATE_DWARF_URL=http://localhost:8001/
|
||||
export DBGFLAGS=-g0
|
||||
# export DBGFLAGS=-g3 -gseparate-dwarf -sSEPARATE_DWARF_URL=http://localhost:8001/
|
||||
|
||||
export OPTFLAGS=-O2
|
||||
export CFLAGS_BASE=\
|
||||
|
|
|
@ -23,6 +23,11 @@ substitutions:
|
|||
|
||||
- Upgraded packages: distlib (0.3.4), lxml (4.8.0) {pr}`2239`, astropy (5.0.2)
|
||||
|
||||
- Many more scipy linking errors were fixed, mostly related to the Fortran f2c
|
||||
ABI for string arguments. There are still some fatal errors in the Scipy test
|
||||
suite, but none seem to be simple linker errors.
|
||||
{pr}`2289`
|
||||
|
||||
### Uncategorized
|
||||
|
||||
- {{Fix}} Fix importing pyodide with ESM syntax in a module type web worker.
|
||||
|
|
|
@ -8,11 +8,12 @@ source:
|
|||
extract_dir: CLAPACK-3.2.1
|
||||
patches:
|
||||
- patches/0001-add-missing-import.patch
|
||||
- patches/0002-fix-arith-h.patch
|
||||
- patches/0002-fix-arith.h.patch
|
||||
- patches/0003-lapack-install-make.patch
|
||||
- patches/0004-fix-f2clibs-build.patch
|
||||
- patches/0005-remove-redundant-symbols.patch
|
||||
- patches/0006-correct-return-types.patch
|
||||
- patches/0007-Fix-xerbla-and-ilaenv.patch
|
||||
extras:
|
||||
- [make.inc, make.inc]
|
||||
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
From c1c714f1217ab6fba5ae1ceb6d0c4a9469490093 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Droettboom <mdboom@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 19:59:05 -0700
|
||||
Subject: [PATCH 1/7] add missing import
|
||||
|
||||
The original source files are missing some imports. gcc assumes implicit
|
||||
function declaration, so the code compiles fine, but emscripten sets
|
||||
-Werror=implicit-function-declaration so it is a hard error.
|
||||
---
|
||||
BLAS/SRC/xerbla.c | 2 ++
|
||||
INSTALL/tstiee.c | 2 ++
|
||||
2 files changed, 4 insertions(+)
|
||||
|
||||
diff --git a/BLAS/SRC/xerbla.c b/BLAS/SRC/xerbla.c
|
||||
index 2d7baf5..da1d7fd 100644
|
||||
--- a/BLAS/SRC/xerbla.c
|
||||
+++ b/BLAS/SRC/xerbla.c
|
||||
@@ -10,6 +10,8 @@
|
||||
|
@ -12,7 +23,9 @@ function declaration, so the code compiles fine, but emscripten sets
|
|||
+
|
||||
#include "f2c.h"
|
||||
#include "blaswrap.h"
|
||||
|
||||
|
||||
diff --git a/INSTALL/tstiee.c b/INSTALL/tstiee.c
|
||||
index 2b5426f..89a41b8 100644
|
||||
--- a/INSTALL/tstiee.c
|
||||
+++ b/INSTALL/tstiee.c
|
||||
@@ -10,6 +10,8 @@
|
||||
|
@ -23,4 +36,7 @@ function declaration, so the code compiles fine, but emscripten sets
|
|||
+
|
||||
#include "f2c.h"
|
||||
#include "blaswrap.h"
|
||||
#include "string.h"
|
||||
--
|
||||
2.25.1
|
||||
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
From 01990867ee7a641078505efba367a413a97f7802 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Droettboom <mdboom@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 19:59:25 -0700
|
||||
Subject: [PATCH 2/7] fix arith.h
|
||||
|
||||
arith.h is a file generated at build time by compiling and running a C program.
|
||||
Since we use emscripten to build throughout, the C program becomes a wasm file
|
||||
and we call it differently.
|
||||
---
|
||||
F2CLIBS/libf2c/Makefile | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/F2CLIBS/libf2c/Makefile b/F2CLIBS/libf2c/Makefile
|
||||
index 0a3ed0d..a473ed8 100644
|
||||
--- a/F2CLIBS/libf2c/Makefile
|
||||
+++ b/F2CLIBS/libf2c/Makefile
|
||||
@@ -184,8 +184,8 @@
|
||||
@@ -173,8 +173,8 @@ xwsne.o: fmt.h
|
||||
arith.h: arithchk.c
|
||||
$(CC) $(CFLAGS) -DNO_FPINIT arithchk.c -lm ||\
|
||||
$(CC) -DNO_LONG_LONG $(CFLAGS) -DNO_FPINIT arithchk.c -lm
|
||||
|
@ -15,3 +25,6 @@ and we call it differently.
|
|||
|
||||
check:
|
||||
xsum Notice README abort_.c arithchk.c backspac.c c_abs.c c_cos.c \
|
||||
--
|
||||
2.25.1
|
||||
|
|
@ -1,18 +1,31 @@
|
|||
From 7b263aed921afdf92525975befd268b0871b8dc4 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Droettboom <mdboom@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 19:59:46 -0700
|
||||
Subject: [PATCH 3/7] lapack install make
|
||||
|
||||
lapack_install requires f2clib (see INSTALL/Makefile).
|
||||
|
||||
Don't run LAPACK_INSTALL tests since they won't actually run on x86
|
||||
---
|
||||
Makefile | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 36c6a0d..4e43b79 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -15,9 +15,8 @@
|
||||
@@ -15,9 +15,8 @@ lib: f2clib blaslib variants lapacklib tmglib
|
||||
|
||||
clean: cleanlib cleantesting cleanblas_testing
|
||||
|
||||
|
||||
-lapack_install:
|
||||
- ( cd INSTALL; $(MAKE); ./testlsame; ./testslamch; \
|
||||
- ./testdlamch; ./testsecond; ./testdsecnd; ./testversion )
|
||||
+lapack_install: f2clib
|
||||
+ ( cd INSTALL; $(MAKE) )
|
||||
|
||||
|
||||
blaslib:
|
||||
( cd BLAS/SRC; $(MAKE) )
|
||||
--
|
||||
2.25.1
|
||||
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
From d88133066f9f6312145c1186116fdb6446d3f7a5 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Droettboom <mdboom@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 20:00:51 -0700
|
||||
Subject: [PATCH 4/7] fix f2clibs build
|
||||
|
||||
emscripten produces LLVM bitcode here, not genuine object files, so it doesn't
|
||||
make sense to strip symbols.
|
||||
|
||||
(It would also fail because emcc uses the file extension to determine what kind
|
||||
of object to output, and .xxx is not a recognized extension; this is the error
|
||||
message you would receive if you try to run the commands)
|
||||
---
|
||||
F2CLIBS/libf2c/Makefile | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/F2CLIBS/libf2c/Makefile b/F2CLIBS/libf2c/Makefile
|
||||
index a473ed8..e51d826 100644
|
||||
--- a/F2CLIBS/libf2c/Makefile
|
||||
+++ b/F2CLIBS/libf2c/Makefile
|
||||
@@ -20,8 +20,6 @@
|
||||
@@ -19,8 +19,6 @@ include ../../make.inc
|
||||
# compile, then strip unnecessary symbols
|
||||
.c.o:
|
||||
$(CC) -c -DSkip_f2c_Undefs $(CFLAGS) $*.c
|
||||
|
@ -16,3 +26,6 @@ message you would receive if you try to run the commands)
|
|||
## Under Solaris (and other systems that do not understand ld -x),
|
||||
## omit -x in the ld line above.
|
||||
## If your system does not have the ld command, comment out
|
||||
--
|
||||
2.25.1
|
||||
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
From 78ff0cec961d9eb4e94193995fe151e1ecdae9df Mon Sep 17 00:00:00 2001
|
||||
From: Roman Yurchak <rth.yurchak@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 20:01:39 -0700
|
||||
Subject: [PATCH 5/7] remove redundant symbols
|
||||
|
||||
Remove a few symbols from LAPACK that are redundantly defined with BLAS or are
|
||||
ported in scipy. It wouldn't be an issue if we were linking dynamically, but
|
||||
because of static linking otherwise we get errors at link time about symbols
|
||||
defined twice.
|
||||
|
||||
- Roman Yurchak (https://github.com/pyodide/pyodide/pull/238)
|
||||
diff --git a/Makefile.orig b/Makefile
|
||||
index 223f4da..69ac630 100644
|
||||
---
|
||||
SRC/Makefile | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/SRC/Makefile b/SRC/Makefile
|
||||
index 5f1eb22..32e669b 100644
|
||||
--- a/SRC/Makefile
|
||||
+++ b/SRC/Makefile
|
||||
@@ -50,9 +50,9 @@ include $(TOPDIR)/make.inc
|
||||
@@ -48,9 +48,9 @@ include ../make.inc
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
|
@ -20,39 +29,6 @@ index 223f4da..69ac630 100644
|
|||
|
||||
ALLXAUX =
|
||||
|
||||
@@ -104,7 +104,7 @@ SLASRC = \
|
||||
sggrqf.o sggsvd.o sggsvp.o sgtcon.o sgtrfs.o sgtsv.o \
|
||||
sgtsvx.o sgttrf.o sgttrs.o sgtts2.o shgeqz.o \
|
||||
shsein.o shseqr.o slabrd.o slacon.o slacn2.o \
|
||||
- slaein.o slaexc.o slag2.o slags2.o slagtm.o slagv2.o slahqr.o \
|
||||
+ slaein.o slaexc.o slag2.o slags2.o slagtm.o slagv2.o \
|
||||
slahrd.o slahr2.o slaic1.o slaln2.o slals0.o slalsa.o slalsd.o \
|
||||
slangb.o slange.o slangt.o slanhs.o slansb.o slansp.o \
|
||||
slansy.o slantb.o slantp.o slantr.o slanv2.o \
|
||||
@@ -176,7 +176,7 @@ CLASRC = \
|
||||
clacgv.o clacon.o clacn2.o clacp2.o clacpy.o clacrm.o clacrt.o cladiv.o \
|
||||
claed0.o claed7.o claed8.o \
|
||||
claein.o claesy.o claev2.o clags2.o clagtm.o \
|
||||
- clahef.o clahqr.o \
|
||||
+ clahef.o \
|
||||
clahrd.o clahr2.o claic1.o clals0.o clalsa.o clalsd.o clangb.o clange.o clangt.o \
|
||||
clanhb.o clanhe.o \
|
||||
clanhp.o clanhs.o clanht.o clansb.o clansp.o clansy.o clantb.o \
|
||||
@@ -236,7 +236,7 @@ DLASRC = \
|
||||
dggrqf.o dggsvd.o dggsvp.o dgtcon.o dgtrfs.o dgtsv.o \
|
||||
dgtsvx.o dgttrf.o dgttrs.o dgtts2.o dhgeqz.o \
|
||||
dhsein.o dhseqr.o dlabrd.o dlacon.o dlacn2.o \
|
||||
- dlaein.o dlaexc.o dlag2.o dlags2.o dlagtm.o dlagv2.o dlahqr.o \
|
||||
+ dlaein.o dlaexc.o dlag2.o dlags2.o dlagtm.o dlagv2.o \
|
||||
dlahrd.o dlahr2.o dlaic1.o dlaln2.o dlals0.o dlalsa.o dlalsd.o \
|
||||
dlangb.o dlange.o dlangt.o dlanhs.o dlansb.o dlansp.o \
|
||||
dlansy.o dlantb.o dlantp.o dlantr.o dlanv2.o \
|
||||
@@ -310,7 +310,7 @@ ZLASRC = \
|
||||
zlacgv.o zlacon.o zlacn2.o zlacp2.o zlacpy.o zlacrm.o zlacrt.o zladiv.o \
|
||||
zlaed0.o zlaed7.o zlaed8.o \
|
||||
zlaein.o zlaesy.o zlaev2.o zlags2.o zlagtm.o \
|
||||
- zlahef.o zlahqr.o \
|
||||
+ zlahef.o \
|
||||
zlahrd.o zlahr2.o zlaic1.o zlals0.o zlalsa.o zlalsd.o zlangb.o zlange.o \
|
||||
zlangt.o zlanhb.o \
|
||||
zlanhe.o \
|
||||
--
|
||||
2.25.1
|
||||
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
From 572a3e20ba040b4f29bbef97a9db6658c10077d3 Mon Sep 17 00:00:00 2001
|
||||
From: Joe Marshall <joe.marshall@nottingham.ac.uk>
|
||||
Date: Fri, 18 Mar 2022 20:02:42 -0700
|
||||
Subject: [PATCH 6/7] correct return types
|
||||
|
||||
Make return types to fortran subroutines consistently be int. Some functions are defined within clapack as variously
|
||||
void and int return. Normal C compilers don't care, but emscripten is strict about return values.
|
||||
---
|
||||
F2CLIBS/libf2c/ef1asc_.c | 2 +-
|
||||
F2CLIBS/libf2c/f2ch.add | 4 ++--
|
||||
F2CLIBS/libf2c/s_cat.c | 6 +++---
|
||||
F2CLIBS/libf2c/s_copy.c | 4 ++--
|
||||
4 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/F2CLIBS/libf2c/ef1asc_.c b/F2CLIBS/libf2c/ef1asc_.c
|
||||
index 70be0bc..b2a82a2 100644
|
||||
--- a/F2CLIBS/libf2c/ef1asc_.c
|
||||
|
@ -64,3 +76,6 @@ index 9dacfc7..8d8963f 100644
|
|||
#endif
|
||||
{
|
||||
register char *aend, *bend;
|
||||
--
|
||||
2.25.1
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
From c0d2a69ac4e4b63c4f28fadb896581164a2e29d3 Mon Sep 17 00:00:00 2001
|
||||
From: Hood Chatham <roberthoodchatham@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 22:07:00 -0700
|
||||
Subject: [PATCH 7/7] Fix xerbla and ilaenv
|
||||
|
||||
These functions take actual C strings as arguments. It is annoying
|
||||
to patch fortran to pass C strings, so this adds a wrapper that
|
||||
'converts' from a Fortran string.
|
||||
---
|
||||
BLAS/SRC/xerbla.c | 6 +++++-
|
||||
SRC/ilaenv.c | 6 ++++++
|
||||
2 files changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/BLAS/SRC/xerbla.c b/BLAS/SRC/xerbla.c
|
||||
index da1d7fd..a6b5ca4 100644
|
||||
--- a/BLAS/SRC/xerbla.c
|
||||
+++ b/BLAS/SRC/xerbla.c
|
||||
@@ -68,7 +68,7 @@ static integer c__1 = 1;
|
||||
/* .. */
|
||||
/* .. Executable Statements .. */
|
||||
|
||||
- printf("** On entry to %6s, parameter number %2i had an illegal value\n",
|
||||
+ printf("** On entry to %s, parameter number %2i had an illegal value\n",
|
||||
srname, *info);
|
||||
|
||||
|
||||
@@ -76,3 +76,7 @@ static integer c__1 = 1;
|
||||
|
||||
return 0;
|
||||
} /* xerbla_ */
|
||||
+
|
||||
+int xerblaf2py_(char *srname, integer *info, integer srnamelen){
|
||||
+ return xerbla_(srname, info);
|
||||
+}
|
||||
diff --git a/SRC/ilaenv.c b/SRC/ilaenv.c
|
||||
index 9565433..b8d28a8 100644
|
||||
--- a/SRC/ilaenv.c
|
||||
+++ b/SRC/ilaenv.c
|
||||
@@ -652,3 +652,9 @@ L160:
|
||||
/* End of ILAENV */
|
||||
|
||||
} /* ilaenv_ */
|
||||
+
|
||||
+integer ilaenvf2py_(integer *ispec, char *name__, char *opts, integer *n1,
|
||||
+ integer *n2, integer *n3, integer *n4, int name_len, int opts_len)
|
||||
+{
|
||||
+ return ilaenv_(ispec, name__, opts, n1, n2, n3, n4);
|
||||
+}
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.25.1
|
||||
|
|
@ -29,6 +29,8 @@ source:
|
|||
- patches/skip-fortran-fails-to-link.patch
|
||||
- patches/rename-_page_trend_test.patch
|
||||
- patches/USE_CPP14-branch-doesn-t-work-for-wasm.patch
|
||||
- patches/0001-Fix-getbreak-dlamch.patch
|
||||
- patches/0001-Fix-dstevr-in-special-lapack_defs.h.patch
|
||||
|
||||
build:
|
||||
cflags: |
|
||||
|
@ -56,6 +58,7 @@ build:
|
|||
sgemqrt.f sgeqrfp.f sgeqrt.f slahqr.f ssyconv.f ssyconvf.f ssyconvf_rook.f stpmqrt.f stpqrt.f \
|
||||
zgemqrt.f zgeqrfp.f zgeqrt.f zlahqr.f zsyconv.f zsyconvf.f zsyconvf_rook.f ztpmqrt.f ztpqrt.f \
|
||||
>> ../../scipy/linalg/lapack_extras.f
|
||||
sed -i 's/CHARACTER/INTEGER/g' ../../scipy/linalg/lapack_extras.f
|
||||
cd ../..
|
||||
# The additional four functions cuncsd, dorcsd, sorcsd, and zuncsd are also
|
||||
# missing but they use features of Fortran that aren't Fortran 77 compatible
|
||||
|
@ -64,15 +67,33 @@ build:
|
|||
|
||||
# Change many functions that return void into functions that return int
|
||||
find scipy -name "*.c*" | xargs sed -i 's/extern void F_FUNC/extern int F_FUNC/g'
|
||||
|
||||
sed -i 's/void F_FUNC/int F_FUNC/g' scipy/odr/__odrpack.c
|
||||
sed -i 's/^void/int/g' scipy/odr/odrpack.h
|
||||
sed -i 's/^void/int/g' scipy/odr/__odrpack.c
|
||||
|
||||
sed -i 's/void BLAS_FUNC/int BLAS_FUNC/g' scipy/special/lapack_defs.h
|
||||
# sed -i 's/void F_FUNC/int F_FUNC/g' scipy/linalg/_lapack_subroutines.h
|
||||
sed -i 's/extern void/extern int/g' scipy/optimize/__minpack.h
|
||||
sed -i 's/^void/int/g' scipy/interpolate/src/_fitpackmodule.c
|
||||
sed -i 's/void/int/g' scipy/linalg/cython_blas_signatures.txt
|
||||
sed -i 's/^void/int/g' scipy/interpolate/src/_fitpackmodule.c
|
||||
|
||||
sed -i 's/^void/int/g' scipy/optimize/_trlib/trlib_private.h
|
||||
sed -i 's/^void/int/g' scipy/optimize/_trlib/trlib/trlib_private.h
|
||||
sed -i 's/, int)/)/g' scipy/optimize/_trlib/trlib_private.h
|
||||
sed -i 's/, 1)/)/g' scipy/optimize/_trlib/trlib_private.h
|
||||
|
||||
sed -i 's/^void/int/g' scipy/spatial/qhull_misc.h
|
||||
sed -i 's/, size_t)/)/g' scipy/spatial/qhull_misc.h
|
||||
sed -i 's/,1)/)/g' scipy/spatial/qhull_misc.h
|
||||
|
||||
|
||||
# Missing declaration from cython_lapack_signatures.txt
|
||||
echo "void ilaenv(int *ispec, char *name, char *opts, int *n1, int *n2, int *n3, int *n4)" \
|
||||
>> scipy/linalg/cython_lapack_signatures.txt
|
||||
|
||||
# sed -i 's/^void/int/g' scipy/linalg/cython_lapack_signatures.txt
|
||||
|
||||
# Input error causes "duplicate symbol" linker errors. Empty out the file.
|
||||
echo "" > scipy/sparse/linalg/dsolve/SuperLU/SRC/input_error.c
|
||||
echo 'import sys' >> scipy/__init__.py
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
From 9aeab0fdc80d21b5a9a88402fdcbdf4c6e0589bc Mon Sep 17 00:00:00 2001
|
||||
From: Hood Chatham <roberthoodchatham@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 16:25:39 -0700
|
||||
Subject: [PATCH] Fix dstevr in special/lapack_defs.h
|
||||
|
||||
---
|
||||
scipy/special/lapack_defs.h | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/scipy/special/lapack_defs.h b/scipy/special/lapack_defs.h
|
||||
index 0d20ba1ca..d4325f71f 100644
|
||||
--- a/scipy/special/lapack_defs.h
|
||||
+++ b/scipy/special/lapack_defs.h
|
||||
@@ -8,13 +8,12 @@ extern void BLAS_FUNC(dstevr)(char *jobz, char *range, CBLAS_INT *n, double *d,
|
||||
double *vl, double *vu, CBLAS_INT *il, CBLAS_INT *iu, double *abstol,
|
||||
CBLAS_INT *m, double *w, double *z, CBLAS_INT *ldz, CBLAS_INT *isuppz,
|
||||
double *work, CBLAS_INT *lwork, CBLAS_INT *iwork, CBLAS_INT *liwork,
|
||||
- CBLAS_INT *info, size_t jobz_len, size_t range_len);
|
||||
+ CBLAS_INT *info);
|
||||
|
||||
static void c_dstevr(char *jobz, char *range, CBLAS_INT *n, double *d, double *e,
|
||||
double *vl, double *vu, CBLAS_INT *il, CBLAS_INT *iu, double *abstol,
|
||||
CBLAS_INT *m, double *w, double *z, CBLAS_INT *ldz, CBLAS_INT *isuppz,
|
||||
double *work, CBLAS_INT *lwork, CBLAS_INT *iwork, CBLAS_INT *liwork, CBLAS_INT *info) {
|
||||
BLAS_FUNC(dstevr)(jobz, range, n, d, e, vl, vu, il, iu, abstol, m,
|
||||
- w, z, ldz, isuppz, work, lwork, iwork, liwork, info,
|
||||
- 1, 1);
|
||||
+ w, z, ldz, isuppz, work, lwork, iwork, liwork, info);
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From 3c96482aec096998e3497f7ca177309a2cef8c62 Mon Sep 17 00:00:00 2001
|
||||
From: Hood Chatham <roberthoodchatham@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 16:06:48 -0700
|
||||
Subject: [PATCH] Fix getbreak dlamch
|
||||
|
||||
---
|
||||
doc/source/_static/scipy-mathjax | 2 +-
|
||||
scipy/sparse/linalg/isolve/iterative/GMRESREVCOM.f.src | 2 +-
|
||||
scipy/sparse/linalg/isolve/iterative/getbreak.f.src | 2 +-
|
||||
3 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/scipy/sparse/linalg/isolve/iterative/GMRESREVCOM.f.src b/scipy/sparse/linalg/isolve/iterative/GMRESREVCOM.f.src
|
||||
index da4bde8ec..5f47afde2 100644
|
||||
--- a/scipy/sparse/linalg/isolve/iterative/GMRESREVCOM.f.src
|
||||
+++ b/scipy/sparse/linalg/isolve/iterative/GMRESREVCOM.f.src
|
||||
@@ -154,7 +154,7 @@
|
||||
INFO = 0
|
||||
MAXIT = ITER
|
||||
BRKDWN = .FALSE.
|
||||
- EPS = <sdsd>LAMCH('EPS')
|
||||
+ EPS = <sdsd>LAMCH(69)
|
||||
*
|
||||
* Alias workspace columns.
|
||||
*
|
||||
diff --git a/scipy/sparse/linalg/isolve/iterative/getbreak.f.src b/scipy/sparse/linalg/isolve/iterative/getbreak.f.src
|
||||
index 6fc6605ac..5472f8f1a 100644
|
||||
--- a/scipy/sparse/linalg/isolve/iterative/getbreak.f.src
|
||||
+++ b/scipy/sparse/linalg/isolve/iterative/getbreak.f.src
|
||||
@@ -9,7 +9,7 @@
|
||||
IMPLICIT NONE
|
||||
<rt> EPS, <sdsd=s,d,s,d>LAMCH
|
||||
*
|
||||
- EPS = <sdsd>LAMCH('EPS')
|
||||
+ EPS = <sdsd>LAMCH(69)
|
||||
<_c>GETBREAK = EPS**2
|
||||
*
|
||||
RETURN
|
||||
--
|
||||
2.25.1
|
||||
|
|
@ -10,300 +10,6 @@ patch fixes implicit casts from char* to int, which we need to deal with manuall
|
|||
|
||||
--- a/scipy/linalg/src/id_dist/src/dfft.c
|
||||
+++ b/scipy/linalg/src/id_dist/src/dfft.c
|
||||
@@ -2855,8 +2855,7 @@ f_rook.f"> */
|
||||
extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen), ctprfb_(
|
||||
char *, char *, char *, char *, integer *, integer *, integer *,
|
||||
integer *, complex *, integer *, complex *, integer *, complex *,
|
||||
- integer *, complex *, integer *, complex *, integer *, ftnlen,
|
||||
- ftnlen, ftnlen, ftnlen);
|
||||
+ integer *, complex *, integer *, complex *, integer *);
|
||||
static logical notran;
|
||||
|
||||
|
||||
@@ -2967,8 +2966,7 @@ f_rook.f"> */
|
||||
}
|
||||
ctprfb_("L", "C", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && notran) {
|
||||
@@ -2989,8 +2987,7 @@ f_rook.f"> */
|
||||
}
|
||||
ctprfb_("R", "N", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
} else if (left && notran) {
|
||||
@@ -3011,8 +3008,7 @@ f_rook.f"> */
|
||||
}
|
||||
ctprfb_("L", "N", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && tran) {
|
||||
@@ -3033,8 +3029,7 @@ f_rook.f"> */
|
||||
}
|
||||
ctprfb_("R", "C", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3247,8 +3242,7 @@ f"> */
|
||||
extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen), ctprfb_(
|
||||
char *, char *, char *, char *, integer *, integer *, integer *,
|
||||
integer *, complex *, integer *, complex *, integer *, complex *,
|
||||
- integer *, complex *, integer *, complex *, integer *, ftnlen,
|
||||
- ftnlen, ftnlen, ftnlen), ctpqrt2_(integer *, integer *, integer *,
|
||||
+ integer *, complex *, integer *, complex *, integer *), ctpqrt2_(integer *, integer *, integer *,
|
||||
complex *, integer *, complex *, integer *, complex *, integer *,
|
||||
integer *);
|
||||
|
||||
@@ -3342,7 +3336,7 @@ f"> */
|
||||
ctprfb_("L", "C", "F", "C", &mb, &i__3, &ib, &lb, &b[i__ * b_dim1
|
||||
+ 1], ldb, &t[i__ * t_dim1 + 1], ldt, &a[i__ + (i__ + ib)
|
||||
* a_dim1], lda, &b[(i__ + ib) * b_dim1 + 1], ldb, &work[1]
|
||||
- , &ib, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1);
|
||||
+ , &ib);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -6041,11 +6035,13 @@ f_rook.f"> */
|
||||
static integer ldvq;
|
||||
extern logical lsame_(char *, char *, ftnlen, ftnlen);
|
||||
static logical right;
|
||||
- extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen), dtprfb_(
|
||||
+ extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen),
|
||||
+
|
||||
+ dtprfb_(
|
||||
char *, char *, char *, char *, integer *, integer *, integer *,
|
||||
integer *, doublereal *, integer *, doublereal *, integer *,
|
||||
doublereal *, integer *, doublereal *, integer *, doublereal *,
|
||||
- integer *, ftnlen, ftnlen, ftnlen, ftnlen);
|
||||
+ integer *);
|
||||
static logical notran;
|
||||
|
||||
|
||||
@@ -6156,8 +6152,7 @@ f_rook.f"> */
|
||||
}
|
||||
dtprfb_("L", "T", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && notran) {
|
||||
@@ -6178,8 +6173,7 @@ f_rook.f"> */
|
||||
}
|
||||
dtprfb_("R", "N", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
} else if (left && notran) {
|
||||
@@ -6200,8 +6194,7 @@ f_rook.f"> */
|
||||
}
|
||||
dtprfb_("L", "N", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && tran) {
|
||||
@@ -6222,8 +6215,7 @@ f_rook.f"> */
|
||||
}
|
||||
dtprfb_("R", "T", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6433,13 +6425,12 @@ f"> */
|
||||
|
||||
/* Local variables */
|
||||
static integer i__, ib, lb, mb, iinfo;
|
||||
- extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen), dtprfb_(
|
||||
- char *, char *, char *, char *, integer *, integer *, integer *,
|
||||
- integer *, doublereal *, integer *, doublereal *, integer *,
|
||||
- doublereal *, integer *, doublereal *, integer *, doublereal *,
|
||||
- integer *, ftnlen, ftnlen, ftnlen, ftnlen), dtpqrt2_(integer *,
|
||||
- integer *, integer *, doublereal *, integer *, doublereal *,
|
||||
- integer *, doublereal *, integer *, integer *);
|
||||
+ extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen),
|
||||
+
|
||||
+dtprfb_(char *, char *, char *, char *, integer *, integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *,
|
||||
+ doublereal *, integer *, doublereal *, integer *, doublereal *, integer *),
|
||||
+
|
||||
+ dtpqrt2_(integer *, integer *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, integer *);
|
||||
|
||||
|
||||
/* -- LAPACK computational routine -- */
|
||||
@@ -6531,9 +6522,8 @@ f"> */
|
||||
dtprfb_("L", "T", "F", "C", &mb, &i__3, &ib, &lb, &b[i__ * b_dim1
|
||||
+ 1], ldb, &t[i__ * t_dim1 + 1], ldt, &a[i__ + (i__ + ib)
|
||||
* a_dim1], lda, &b[(i__ + ib) * b_dim1 + 1], ldb, &work[1]
|
||||
- , &ib, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1);
|
||||
- }
|
||||
- }
|
||||
+ , &ib);
|
||||
+ }}
|
||||
return 0;
|
||||
|
||||
/* End of DTPQRT */
|
||||
@@ -9226,8 +9216,7 @@ f_rook.f"> */
|
||||
extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen), stprfb_(
|
||||
char *, char *, char *, char *, integer *, integer *, integer *,
|
||||
integer *, real *, integer *, real *, integer *, real *, integer *
|
||||
- , real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen,
|
||||
- ftnlen);
|
||||
+ , real *, integer *, real *, integer *);
|
||||
static logical notran;
|
||||
|
||||
|
||||
@@ -9338,8 +9327,7 @@ f_rook.f"> */
|
||||
}
|
||||
stprfb_("L", "T", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && notran) {
|
||||
@@ -9360,8 +9348,7 @@ f_rook.f"> */
|
||||
}
|
||||
stprfb_("R", "N", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
} else if (left && notran) {
|
||||
@@ -9382,8 +9369,7 @@ f_rook.f"> */
|
||||
}
|
||||
stprfb_("L", "N", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && tran) {
|
||||
@@ -9404,8 +9390,7 @@ f_rook.f"> */
|
||||
}
|
||||
stprfb_("R", "T", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9618,8 +9603,7 @@ f"> */
|
||||
extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen), stprfb_(
|
||||
char *, char *, char *, char *, integer *, integer *, integer *,
|
||||
integer *, real *, integer *, real *, integer *, real *, integer *
|
||||
- , real *, integer *, real *, integer *, ftnlen, ftnlen, ftnlen,
|
||||
- ftnlen), stpqrt2_(integer *, integer *, integer *, real *,
|
||||
+ , real *, integer *, real *, integer *), stpqrt2_(integer *, integer *, integer *, real *,
|
||||
integer *, real *, integer *, real *, integer *, integer *);
|
||||
|
||||
|
||||
@@ -9712,7 +9696,7 @@ f"> */
|
||||
stprfb_("L", "T", "F", "C", &mb, &i__3, &ib, &lb, &b[i__ * b_dim1
|
||||
+ 1], ldb, &t[i__ * t_dim1 + 1], ldt, &a[i__ + (i__ + ib)
|
||||
* a_dim1], lda, &b[(i__ + ib) * b_dim1 + 1], ldb, &work[1]
|
||||
- , &ib, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1);
|
||||
+ , &ib);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -12502,8 +12486,7 @@ f_rook.f"> */
|
||||
extern /* Subroutine */ int ztprfb_(char *, char *, char *, char *,
|
||||
integer *, integer *, integer *, integer *, doublecomplex *,
|
||||
integer *, doublecomplex *, integer *, doublecomplex *, integer *,
|
||||
- doublecomplex *, integer *, doublecomplex *, integer *, ftnlen,
|
||||
- ftnlen, ftnlen, ftnlen);
|
||||
+ doublecomplex *, integer *, doublecomplex *, integer *);
|
||||
|
||||
|
||||
/* -- LAPACK computational routine -- */
|
||||
@@ -12613,8 +12596,7 @@ f_rook.f"> */
|
||||
}
|
||||
ztprfb_("L", "C", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && notran) {
|
||||
@@ -12635,8 +12617,7 @@ f_rook.f"> */
|
||||
}
|
||||
ztprfb_("R", "N", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
} else if (left && notran) {
|
||||
@@ -12657,8 +12638,7 @@ f_rook.f"> */
|
||||
}
|
||||
ztprfb_("L", "N", "F", "C", &mb, n, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ + a_dim1], lda, &
|
||||
- b[b_offset], ldb, &work[1], &ib, (ftnlen)1, (ftnlen)1, (
|
||||
- ftnlen)1, (ftnlen)1);
|
||||
+ b[b_offset], ldb, &work[1], &ib);
|
||||
}
|
||||
|
||||
} else if (right && tran) {
|
||||
@@ -12679,8 +12659,7 @@ f_rook.f"> */
|
||||
}
|
||||
ztprfb_("R", "C", "F", "C", m, &mb, &ib, &lb, &v[i__ * v_dim1 + 1]
|
||||
, ldv, &t[i__ * t_dim1 + 1], ldt, &a[i__ * a_dim1 + 1],
|
||||
- lda, &b[b_offset], ldb, &work[1], m, (ftnlen)1, (ftnlen)1,
|
||||
- (ftnlen)1, (ftnlen)1);
|
||||
+ lda, &b[b_offset], ldb, &work[1], m);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12894,7 +12873,7 @@ f"> */
|
||||
char *, char *, char *, char *, integer *, integer *, integer *,
|
||||
integer *, doublecomplex *, integer *, doublecomplex *, integer *,
|
||||
doublecomplex *, integer *, doublecomplex *, integer *,
|
||||
- doublecomplex *, integer *, ftnlen, ftnlen, ftnlen, ftnlen),
|
||||
+ doublecomplex *, integer *),
|
||||
ztpqrt2_(integer *, integer *, integer *, doublecomplex *,
|
||||
integer *, doublecomplex *, integer *, doublecomplex *, integer *,
|
||||
integer *);
|
||||
@@ -12989,7 +12968,7 @@ f"> */
|
||||
ztprfb_("L", "C", "F", "C", &mb, &i__3, &ib, &lb, &b[i__ * b_dim1
|
||||
+ 1], ldb, &t[i__ * t_dim1 + 1], ldt, &a[i__ + (i__ + ib)
|
||||
* a_dim1], lda, &b[(i__ + ib) * b_dim1 + 1], ldb, &work[1]
|
||||
- , &ib, (ftnlen)1, (ftnlen)1, (ftnlen)1, (ftnlen)1);
|
||||
+ , &ib);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -12998,3 +12977,10 @@ f"> */
|
||||
|
||||
} /* ztpqrt_ */
|
||||
|
|
|
@ -3,7 +3,7 @@ from pyodide_build import testing
|
|||
run_in_pyodide = testing.run_in_pyodide(
|
||||
module_scope=True,
|
||||
packages=["scipy"],
|
||||
xfail_browsers={"chrome": "Times out in chrome"},
|
||||
# xfail_browsers={"chrome": "Times out in chrome"},
|
||||
driver_timeout=40,
|
||||
)
|
||||
|
||||
|
@ -43,3 +43,24 @@ def test_binom_ppf():
|
|||
from scipy.stats import binom
|
||||
|
||||
assert binom.ppf(0.9, 1000, 0.1) == 112
|
||||
|
||||
|
||||
@testing.run_in_pyodide(module_scope=True, packages=["pytest", "scipy-tests"])
|
||||
def test_scipy_pytest():
|
||||
import pytest
|
||||
|
||||
def runtest(module, filter):
|
||||
pytest.main(
|
||||
[
|
||||
"--pyargs",
|
||||
f"scipy.{module}",
|
||||
"--continue-on-collection-errors",
|
||||
"-vv",
|
||||
"-k",
|
||||
filter,
|
||||
]
|
||||
)
|
||||
|
||||
runtest("odr", "explicit")
|
||||
runtest("signal.tests.test_ltisys", "TestImpulse2")
|
||||
runtest("stats.tests.test_multivariate", "haar")
|
||||
|
|
|
@ -5,6 +5,180 @@ from textwrap import dedent # for doctests
|
|||
from typing import Iterable, Iterator
|
||||
|
||||
|
||||
def prepare_doctest(x):
|
||||
return dedent(x).strip().splitlines(True)
|
||||
|
||||
|
||||
def fix_f2c_input(f2c_input_path: str):
|
||||
"""
|
||||
CLAPACK has been manually modified to remove useless arguments generated by
|
||||
f2c. But the mismatches between the f2c ABI and the human-curated sensible
|
||||
ABI in CLAPACK cause us great pain.
|
||||
|
||||
This stuff applies to actual source files, but scipy also has multiple
|
||||
templating engines for Fortran, so these changes have to be applied
|
||||
immediately prior to f2c'ing a .f file to ensure that they also work
|
||||
correctly on templated files.
|
||||
|
||||
Fortran seems to be mostly case insensitive. The templated files in
|
||||
particular can include weird mixtures of lower and upper case.
|
||||
|
||||
Mostly the issues are related to 'character' types. Most LAPACK functions
|
||||
that take string arguments use them as enums and only care about the first
|
||||
character of the string. f2c generates a 'length' argument to indicate how
|
||||
long the string is, but CLAPACK leaves these length arguments out because
|
||||
the strings are assumed to have length 1.
|
||||
|
||||
So the goal is to cause f2c to generate no length argument. We can achieve
|
||||
this by replacing the string with the ascii code of the first character
|
||||
e.g.,:
|
||||
|
||||
f('UPPER') --> f(85)
|
||||
|
||||
Coming from C this surprises me a bit. I would expect `f(85)` to cause a
|
||||
segfault or something when f tries to find its string at memory address 85.
|
||||
|
||||
f("UPPER") gets f2c'd to:
|
||||
|
||||
f("UPPER", 5)
|
||||
|
||||
But f2c compiles f(85) to the C code:
|
||||
|
||||
static integer c__85 = 85;
|
||||
f(&c__85);
|
||||
|
||||
This is perfect. Not sure why it does this, but it's very convenient for us.
|
||||
|
||||
chla_transtype is a special case. The CLAPACK version of chla_transtype takes
|
||||
a return argument, whereas f2c thinks it should return the value.
|
||||
|
||||
"""
|
||||
f2c_input = Path(f2c_input_path)
|
||||
with open(f2c_input) as f:
|
||||
lines = f.readlines()
|
||||
new_lines = []
|
||||
lines = char1_args_to_int(lines)
|
||||
|
||||
for line in lines:
|
||||
line = fix_string_args(line)
|
||||
|
||||
if f2c_input_path.endswith("_flapack-f2pywrappers.f"):
|
||||
line = line.replace("character cmach", "integer cmach")
|
||||
line = line.replace("character norm", "integer norm")
|
||||
if "id_dist" in str(f2c_input):
|
||||
line = line.replace("character*1 jobz", "integer jobz")
|
||||
if "jobz =" in line:
|
||||
line = re.sub("'(.)'", lambda r: str(ord(r.group(1))), line)
|
||||
|
||||
if f2c_input.name in [
|
||||
"_lapack_subroutine_wrappers.f",
|
||||
"_blas_subroutine_wrappers.f",
|
||||
]:
|
||||
line = line.replace("character", "integer")
|
||||
line = line.replace("ret = chla_transtype(", "call chla_transtype(ret, 1,")
|
||||
|
||||
new_lines.append(line)
|
||||
|
||||
with open(f2c_input_path, "w") as f:
|
||||
f.writelines(new_lines)
|
||||
|
||||
|
||||
def fix_string_args(line):
|
||||
"""
|
||||
The two functions ilaenv and xerbla have real string args, f2c generates
|
||||
inaccurate signatures for them. Instead of manually fixing the signatures
|
||||
(xerbla happens a lot) we inject wrappers called `xerblaf2py` and
|
||||
`ilaenvf2py` that have the signatures f2c expects and call these instead.
|
||||
|
||||
Also, replace all single character strings in (the first line of) "call"
|
||||
statements with their ascci codes.
|
||||
"""
|
||||
line = re.sub("ilaenv", "ilaenvf2py", line, flags=re.I)
|
||||
if not re.search("call", line, re.I):
|
||||
return line
|
||||
if re.search("xerbla", line, re.I):
|
||||
return re.sub("xerbla", "xerblaf2py", line, flags=re.I)
|
||||
else:
|
||||
return re.sub("'[A-Za-z0-9]'", lambda y: str(ord(y.group(0)[1])), line)
|
||||
|
||||
|
||||
def char1_to_int(x):
|
||||
"""
|
||||
Replace multicharacter strings with the ascii code of their first character.
|
||||
|
||||
>>> char1_to_int("CALL sTRSV( 'UPPER', 'NOTRANS', 'NONUNIT', J, H, LDH, Y, 1 )")
|
||||
'CALL sTRSV( 85, 78, 78, J, H, LDH, Y, 1 )'
|
||||
"""
|
||||
return re.sub("'(.)[A-Za-z -]*'", lambda r: str(ord(r.group(1))), x)
|
||||
|
||||
|
||||
def char1_args_to_int(lines):
|
||||
"""
|
||||
Replace strings with the ascii code of their first character if they are
|
||||
arguments to one of a long list of hard coded LAPACK functions (see
|
||||
fncstems). This handles multiline function calls.
|
||||
|
||||
>>> print(char1_args_to_int(["CALL sTRSV( 'UPPER', 'NOTRANS', 'NONUNIT', J, H, LDH, Y, 1 )"]))
|
||||
['CALL sTRSV( 85, 78, 78, J, H, LDH, Y, 1 )']
|
||||
|
||||
>>> print("".join(char1_args_to_int(prepare_doctest('''
|
||||
... call cvout (logfil, nconv, workl(ihbds), ndigit,
|
||||
... & '_neupd: Last row of the eigenvector matrix for T')
|
||||
... call ctrmm('Right' , 'Upper' , 'No transpose',
|
||||
... & 'Non-unit', n , nconv ,
|
||||
... & one , workl(invsub), ldq ,
|
||||
... & z , ldz)
|
||||
... '''))))
|
||||
call cvout (logfil, nconv, workl(ihbds), ndigit,
|
||||
& '_neupd: Last row of the eigenvector matrix for T')
|
||||
call ctrmm(82 , 85 , 78,
|
||||
& 78, n , nconv ,
|
||||
& one , workl(invsub), ldq ,
|
||||
& z , ldz)
|
||||
"""
|
||||
fncstems = [
|
||||
"gemm",
|
||||
"ggbak",
|
||||
"gghrd",
|
||||
"lacpy",
|
||||
"lamch",
|
||||
"lanhs",
|
||||
"lanst",
|
||||
"larf",
|
||||
"lascl",
|
||||
"laset",
|
||||
"lasr",
|
||||
"ormqr",
|
||||
"orm2r",
|
||||
"steqr",
|
||||
"stevr",
|
||||
"trevc",
|
||||
"trmm",
|
||||
"trsen",
|
||||
"trsv",
|
||||
"unm2r",
|
||||
"unmqr",
|
||||
]
|
||||
fncnames = []
|
||||
for c in "cdsz":
|
||||
for stem in fncstems:
|
||||
fncnames.append(c + stem)
|
||||
fncnames += ["lsame"]
|
||||
|
||||
funcs_pattern = "|".join(fncnames)
|
||||
new_lines = []
|
||||
replace = False
|
||||
for line in lines:
|
||||
if re.search(funcs_pattern, line, re.IGNORECASE):
|
||||
replace = True
|
||||
if replace:
|
||||
line = char1_to_int(line)
|
||||
if not re.search(r",\s*$", line):
|
||||
replace = False
|
||||
new_lines.append(line)
|
||||
return new_lines
|
||||
|
||||
|
||||
def fix_f2c_output(f2c_output_path: str):
|
||||
"""
|
||||
This function is called on the name of each C output file. It fixes up the C
|
||||
|
@ -15,7 +189,8 @@ def fix_f2c_output(f2c_output_path: str):
|
|||
if f2c_output.name == "lapack_extras.c":
|
||||
# dfft.c has a bunch of implicit cast args coming from functions copied
|
||||
# out of future lapack versions. fix_inconsistent_decls will fix all
|
||||
# except string to int.
|
||||
# except string to int. String to int is fixed by fix_string_args and
|
||||
# char1_args_to_int above.
|
||||
subprocess.check_call(
|
||||
[
|
||||
"patch",
|
||||
|
@ -45,50 +220,16 @@ def fix_f2c_output(f2c_output_path: str):
|
|||
else:
|
||||
add_externs_to_structs(lines)
|
||||
|
||||
if f2c_output.name in [
|
||||
"wrap_dummy_g77_abi.c",
|
||||
"_lapack_subroutine_wrappers.c",
|
||||
"_blas_subroutine_wrappers.c",
|
||||
"_flapack-f2pywrappers.c",
|
||||
]:
|
||||
lines = remove_ftnlen_args(lines)
|
||||
if f2c_output.name == "_lapack_subroutine_wrappers.c":
|
||||
lines = [
|
||||
line.replace("integer chla_transtype__", "void chla_transtype__")
|
||||
for line in lines
|
||||
]
|
||||
|
||||
with open(f2c_output, "w") as f:
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def prepare_doctest(x):
|
||||
return dedent(x).strip().split("\n")
|
||||
|
||||
|
||||
def remove_ftnlen_args(lines: list[str]) -> list[str]:
|
||||
"""
|
||||
Functions with "character" arguments have these extra ftnlen arguments at
|
||||
the end (which are never used). Other places declare these arguments as
|
||||
"integer" which don't get length arguments. This automates the removal of
|
||||
the problematic arguments.
|
||||
|
||||
>>> print("\\n".join(remove_ftnlen_args(prepare_doctest('''
|
||||
... /* Subroutine */ int chla_transtypewrp__(char *ret, integer *trans, ftnlen
|
||||
... ret_len)
|
||||
... '''))))
|
||||
/* Subroutine */ int chla_transtypewrp__(char *ret, integer *trans)
|
||||
|
||||
>>> print("\\n".join(remove_ftnlen_args(prepare_doctest('''
|
||||
... /* Subroutine */ int clanhfwrp_(real *ret, char *norm, char *transr, char *
|
||||
... uplo, integer *n, complex *a, real *work, ftnlen norm_len, ftnlen
|
||||
... transr_len, ftnlen uplo_len)
|
||||
... '''))))
|
||||
/* Subroutine */ int clanhfwrp_(real *ret, char *norm, char *transr, char * uplo, integer *n, complex *a, real *work)
|
||||
"""
|
||||
new_lines = []
|
||||
for line in regroup_lines(lines):
|
||||
if line.startswith("/* Subroutine */"):
|
||||
line = re.sub(r",\s*ftnlen [a-z]*_len", "", line)
|
||||
new_lines.append(line)
|
||||
return new_lines
|
||||
|
||||
|
||||
def add_externs_to_structs(lines: list[str]):
|
||||
"""
|
||||
The fortran "common" keyword is supposed to share variables between a bunch
|
||||
|
@ -108,7 +249,7 @@ def add_externs_to_structs(lines: list[str]):
|
|||
... } eh0001_;
|
||||
... ''')
|
||||
>>> add_externs_to_structs(lines)
|
||||
>>> print("\\n".join(lines))
|
||||
>>> print("".join(lines))
|
||||
extern struct { doublereal rls[218];
|
||||
integer ils[39];
|
||||
} ls0001_;
|
||||
|
@ -128,7 +269,7 @@ def regroup_lines(lines: Iterable[str]) -> Iterator[str]:
|
|||
Make sure that functions and declarations have their argument list only on
|
||||
one line.
|
||||
|
||||
>>> print("\\n".join(regroup_lines(prepare_doctest('''
|
||||
>>> print("".join(regroup_lines(prepare_doctest('''
|
||||
... /* Subroutine */ int clanhfwrp_(real *ret, char *norm, char *transr, char *
|
||||
... uplo, integer *n, complex *a, real *work, ftnlen norm_len, ftnlen
|
||||
... transr_len, ftnlen uplo_len)
|
||||
|
@ -137,8 +278,7 @@ def regroup_lines(lines: Iterable[str]) -> Iterator[str]:
|
|||
... extern /* Subroutine */ int dqelg_(integer *, doublereal *, doublereal *,
|
||||
... doublereal *, doublereal *, integer *);
|
||||
... '''))))
|
||||
/* Subroutine */ int clanhfwrp_(real *ret, char *norm, char *transr, char * uplo, integer *n, complex *a, real *work, ftnlen norm_len, ftnlen transr_len, ftnlen uplo_len)
|
||||
{
|
||||
/* Subroutine */ int clanhfwrp_(real *ret, char *norm, char *transr, char * uplo, integer *n, complex *a, real *work, ftnlen norm_len, ftnlen transr_len, ftnlen uplo_len){
|
||||
static doublereal psum[52];
|
||||
extern /* Subroutine */ int dqelg_(integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *);
|
||||
|
||||
|
@ -196,7 +336,7 @@ def fix_inconsistent_decls(lines: list[str]) -> list[str]:
|
|||
declarations and fixes them if necessary so that the declaration matches the
|
||||
definition.
|
||||
|
||||
>>> print("\\n".join(fix_inconsistent_decls(prepare_doctest('''
|
||||
>>> print("".join(fix_inconsistent_decls(prepare_doctest('''
|
||||
... /* Subroutine */ double f(double x){
|
||||
... return x + 5;
|
||||
... }
|
||||
|
@ -260,6 +400,11 @@ def get_subroutine_decl(sub: str) -> tuple[str, list[str]]:
|
|||
|
||||
|
||||
def scipy_fix_cfile(path):
|
||||
"""
|
||||
Replace void return types with int return types in various generated .c and
|
||||
.h files. We can't achieve this with a simple patch because these files are
|
||||
not in the sdist, they are generated as part of the build.
|
||||
"""
|
||||
source_path = Path(path)
|
||||
text = source_path.read_text()
|
||||
text = text.replace("extern void F_WRAPPEDFUNC", "extern int F_WRAPPEDFUNC")
|
||||
|
|
|
@ -31,7 +31,7 @@ from typing import Any, MutableMapping, NoReturn, Optional, overload
|
|||
# absolute import is necessary as this file will be symlinked
|
||||
# under tools
|
||||
from . import common
|
||||
from ._f2c_fixes import fix_f2c_output, scipy_fixes
|
||||
from ._f2c_fixes import fix_f2c_input, fix_f2c_output, scipy_fixes
|
||||
|
||||
symlinks = {"cc", "c++", "ld", "ar", "gcc", "gfortran"}
|
||||
|
||||
|
@ -151,6 +151,7 @@ def replay_f2c(args: list[str], dryrun: bool = False) -> Optional[list[str]]:
|
|||
if arg.endswith(".f"):
|
||||
filename = os.path.abspath(arg)
|
||||
if not dryrun:
|
||||
fix_f2c_input(arg)
|
||||
subprocess.check_call(
|
||||
["f2c", os.path.basename(filename)], cwd=os.path.dirname(filename)
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue