/
lapack.py
116 lines (104 loc) · 3.74 KB
/
lapack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
## Automatically adapted for scipy Oct 18, 2005 by
#
# Author: Pearu Peterson, March 2002
#
__all__ = ['get_lapack_funcs']
import new
# The following ensures that possibly missing flavor (C or Fortran) is
# replaced with the available one. If none is available, exception
# is raised at the first attempt to use the resources.
import numpy
from scipy.linalg import flapack
from scipy.linalg import clapack
_use_force_clapack = 1
if hasattr(clapack,'empty_module'):
clapack = flapack
_use_force_clapack = 0
elif hasattr(flapack,'empty_module'):
flapack = clapack
def cast_to_lapack_prefix(t):
if issubclass(t, numpy.single):
prefix = 's'
elif issubclass(t, numpy.double):
prefix = 'd'
elif issubclass(t, numpy.longdouble):
prefix = 'd'
elif issubclass(t, numpy.csingle):
prefix = 'c'
elif issubclass(t, numpy.cdouble):
prefix = 'z'
elif issubclass(t, numpy.clongdouble):
prefix = 'z'
else:
prefix = 'd'
return prefix
prefix_to_order = dict(s=3, d=2, c=1, z=0)
order_to_prefix = ['s', 'd', 'c', 'z']
prefix_to_dtype = dict(s=numpy.single, d=numpy.double,
c=numpy.csingle, z=numpy.cdouble)
def find_best_lapack_type(arrays):
if not arrays:
return 'd', numpy.double, False
ordering = []
for i in range(len(arrays)):
t = arrays[i].dtype.type
prefix = cast_to_lapack_prefix(t)
order = prefix_to_order[prefix]
ordering.append((order, prefix, i))
ordering.sort()
_, required_prefix, lowest_array_index = ordering[0]
dtype = prefix_to_dtype[required_prefix]
isfortran = numpy.isfortran(arrays[lowest_array_index])
return required_prefix, dtype, isfortran
def get_lapack_funcs(names, arrays=()):
"""Return available LAPACK function objects with names.
arrays are used to determine the optimal prefix of
LAPACK routines.
"""
#If force_clapack is True then available Atlas routine
#is returned for column major storaged arrays with
#rowmajor argument set to False.
force_clapack=False #XXX: Don't set it true! The feature is unreliable
# and may cause incorrect results.
# See test_basic.test_solve.check_20Feb04_bug.
required_prefix, dtype, isfortran = find_best_lapack_type(arrays)
# Default lookup:
if isfortran:
# prefer Fortran code for leading array with column major order
m1, m2 = flapack, clapack
else:
# in all other cases, C code is preferred
m1, m2 = clapack, flapack
if not _use_force_clapack:
force_clapack = False
funcs = []
m1_name = m1.__name__.split('.')[-1]
m2_name = m2.__name__.split('.')[-1]
for name in names:
func_name = required_prefix + name
func = getattr(m1,func_name,None)
if func is None:
func = getattr(m2,func_name)
func.module_name = m2_name
else:
func.module_name = m1_name
if force_clapack and m1 is flapack:
func2 = getattr(m2,func_name,None)
if func2 is not None:
exec _colmajor_func_template % {'func_name':func_name}
func = new.function(func_code,
{'clapack_func':func2},
func_name)
func.module_name = m2_name
func.__doc__ = func2.__doc__
func.prefix = required_prefix
func.dtype = dtype
funcs.append(func)
return tuple(funcs)
_colmajor_func_template = '''\
def %(func_name)s(*args,**kws):
if not kws.has_key("rowmajor"):
kws["rowmajor"] = 0
return clapack_func(*args,**kws)
func_code = %(func_name)s.func_code
'''