17
17
atlas_3_10_blas_threads_info,
18
18
lapack_atlas_3_10_info
19
19
lapack_atlas_3_10_threads_info
20
+ flame_info
20
21
blas_info
21
22
lapack_info
22
23
openblas_info
@@ -389,6 +390,7 @@ def get_info(name, notfound_action=0):
389
390
'atlas_3_10_blas_threads' : atlas_3_10_blas_threads_info ,
390
391
'lapack_atlas_3_10' : lapack_atlas_3_10_info , # use lapack_opt instead
391
392
'lapack_atlas_3_10_threads' : lapack_atlas_3_10_threads_info , # ditto
393
+ 'flame' : flame_info , # use lapack_opt instead
392
394
'mkl' : mkl_info ,
393
395
# openblas which may or may not have embedded lapack
394
396
'openblas' : openblas_info , # use blas_opt instead
@@ -464,6 +466,13 @@ class AtlasNotFoundError(NotFoundError):
464
466
the ATLAS environment variable."""
465
467
466
468
469
+ class FlameNotFoundError (NotFoundError ):
470
+ """
471
+ FLAME (http://www.cs.utexas.edu/~flame/web/) libraries not found.
472
+ Directories to search for the libraries can be specified in the
473
+ numpy/distutils/site.cfg file (section [flame])."""
474
+
475
+
467
476
class LapackNotFoundError (NotFoundError ):
468
477
"""
469
478
Lapack (http://www.netlib.org/lapack/) libraries not found.
@@ -1591,7 +1600,7 @@ class lapack_opt_info(system_info):
1591
1600
1592
1601
notfounderror = LapackNotFoundError
1593
1602
# Default order of LAPACK checks
1594
- lapack_order = ['mkl' , 'openblas' , 'atlas' , 'accelerate' , 'lapack' ]
1603
+ lapack_order = ['mkl' , 'openblas' , 'flame' , ' atlas' , 'accelerate' , 'lapack' ]
1595
1604
1596
1605
def _calc_info_mkl (self ):
1597
1606
info = get_info ('lapack_mkl' )
@@ -1611,6 +1620,13 @@ def _calc_info_openblas(self):
1611
1620
return True
1612
1621
return False
1613
1622
1623
+ def _calc_info_flame (self ):
1624
+ info = get_info ('flame' )
1625
+ if info :
1626
+ self .set_info (** info )
1627
+ return True
1628
+ return False
1629
+
1614
1630
def _calc_info_atlas (self ):
1615
1631
info = get_info ('atlas_3_10_threads' )
1616
1632
if not info :
@@ -2043,6 +2059,82 @@ def calc_info(self):
2043
2059
include_dirs = incl_dirs )
2044
2060
self .set_info (** info )
2045
2061
2062
+
2063
+ class flame_info (system_info ):
2064
+ """ Usage of libflame for LAPACK operations
2065
+
2066
+ This requires libflame to be compiled with lapack wrappers:
2067
+
2068
+ ./configure --enable-lapack2flame ...
2069
+
2070
+ Be aware that libflame 5.1.0 has some missing names in the shared library, so
2071
+ if you have problems, try the static flame library.
2072
+ """
2073
+ section = 'flame'
2074
+ _lib_names = ['flame' ]
2075
+ notfounderror = FlameNotFoundError
2076
+
2077
+ def check_embedded_lapack (self , info ):
2078
+ """ libflame does not necessarily have a wrapper for fortran LAPACK, we need to check """
2079
+ c = customized_ccompiler ()
2080
+
2081
+ tmpdir = tempfile .mkdtemp ()
2082
+ s = """void zungqr_();
2083
+ int main(int argc, const char *argv[])
2084
+ {
2085
+ zungqr_();
2086
+ return 0;
2087
+ }"""
2088
+ src = os .path .join (tmpdir , 'source.c' )
2089
+ out = os .path .join (tmpdir , 'a.out' )
2090
+ # Add the additional "extra" arguments
2091
+ extra_args = info .get ('extra_link_args' , [])
2092
+ try :
2093
+ with open (src , 'wt' ) as f :
2094
+ f .write (s )
2095
+ obj = c .compile ([src ], output_dir = tmpdir )
2096
+ try :
2097
+ c .link_executable (obj , out , libraries = info ['libraries' ],
2098
+ library_dirs = info ['library_dirs' ],
2099
+ extra_postargs = extra_args )
2100
+ return True
2101
+ except distutils .ccompiler .LinkError :
2102
+ return False
2103
+ finally :
2104
+ shutil .rmtree (tmpdir )
2105
+
2106
+ def calc_info (self ):
2107
+ lib_dirs = self .get_lib_dirs ()
2108
+ flame_libs = self .get_libs ('libraries' , self ._lib_names )
2109
+
2110
+ info = self .check_libs2 (lib_dirs , flame_libs , [])
2111
+ if info is None :
2112
+ return
2113
+
2114
+ if self .check_embedded_lapack (info ):
2115
+ # check if the user has supplied all information required
2116
+ self .set_info (** info )
2117
+ else :
2118
+ # Try and get the BLAS lib to see if we can get it to work
2119
+ blas_info = get_info ('blas_opt' )
2120
+ if not blas_info :
2121
+ # since we already failed once, this ain't going to work either
2122
+ return
2123
+
2124
+ # Now we need to merge the two dictionaries
2125
+ for key in blas_info :
2126
+ if isinstance (blas_info [key ], list ):
2127
+ info [key ] = info .get (key , []) + blas_info [key ]
2128
+ elif isinstance (blas_info [key ], tuple ):
2129
+ info [key ] = info .get (key , ()) + blas_info [key ]
2130
+ else :
2131
+ info [key ] = info .get (key , '' ) + blas_info [key ]
2132
+
2133
+ # Now check again
2134
+ if self .check_embedded_lapack (info ):
2135
+ self .set_info (** info )
2136
+
2137
+
2046
2138
class accelerate_info (system_info ):
2047
2139
section = 'accelerate'
2048
2140
_lib_names = ['accelerate' , 'veclib' ]
0 commit comments