396 lines
8.5 KiB
Python
396 lines
8.5 KiB
Python
|
"""
|
||
|
Low-level BLAS functions (:mod:`scipy.linalg.blas`)
|
||
|
===================================================
|
||
|
|
||
|
This module contains low-level functions from the BLAS library.
|
||
|
|
||
|
.. versionadded:: 0.12.0
|
||
|
|
||
|
.. note::
|
||
|
|
||
|
The common ``overwrite_<>`` option in many routines, allows the
|
||
|
input arrays to be overwritten to avoid extra memory allocation.
|
||
|
However this requires the array to satisfy two conditions
|
||
|
which are memory order and the data type to match exactly the
|
||
|
order and the type expected by the routine.
|
||
|
|
||
|
As an example, if you pass a double precision float array to any
|
||
|
``S....`` routine which expects single precision arguments, f2py
|
||
|
will create an intermediate array to match the argument types and
|
||
|
overwriting will be performed on that intermediate array.
|
||
|
|
||
|
Similarly, if a C-contiguous array is passed, f2py will pass a
|
||
|
FORTRAN-contiguous array internally. Please make sure that these
|
||
|
details are satisfied. More information can be found in the f2py
|
||
|
documentation.
|
||
|
|
||
|
.. warning::
|
||
|
|
||
|
These functions do little to no error checking.
|
||
|
It is possible to cause crashes by mis-using them,
|
||
|
so prefer using the higher-level routines in `scipy.linalg`.
|
||
|
|
||
|
Finding functions
|
||
|
-----------------
|
||
|
|
||
|
.. autosummary::
|
||
|
:toctree: generated/
|
||
|
|
||
|
get_blas_funcs
|
||
|
find_best_blas_type
|
||
|
|
||
|
BLAS Level 1 functions
|
||
|
----------------------
|
||
|
|
||
|
.. autosummary::
|
||
|
:toctree: generated/
|
||
|
|
||
|
caxpy
|
||
|
ccopy
|
||
|
cdotc
|
||
|
cdotu
|
||
|
crotg
|
||
|
cscal
|
||
|
csrot
|
||
|
csscal
|
||
|
cswap
|
||
|
dasum
|
||
|
daxpy
|
||
|
dcopy
|
||
|
ddot
|
||
|
dnrm2
|
||
|
drot
|
||
|
drotg
|
||
|
drotm
|
||
|
drotmg
|
||
|
dscal
|
||
|
dswap
|
||
|
dzasum
|
||
|
dznrm2
|
||
|
icamax
|
||
|
idamax
|
||
|
isamax
|
||
|
izamax
|
||
|
sasum
|
||
|
saxpy
|
||
|
scasum
|
||
|
scnrm2
|
||
|
scopy
|
||
|
sdot
|
||
|
snrm2
|
||
|
srot
|
||
|
srotg
|
||
|
srotm
|
||
|
srotmg
|
||
|
sscal
|
||
|
sswap
|
||
|
zaxpy
|
||
|
zcopy
|
||
|
zdotc
|
||
|
zdotu
|
||
|
zdrot
|
||
|
zdscal
|
||
|
zrotg
|
||
|
zscal
|
||
|
zswap
|
||
|
|
||
|
BLAS Level 2 functions
|
||
|
----------------------
|
||
|
|
||
|
.. autosummary::
|
||
|
:toctree: generated/
|
||
|
|
||
|
sgbmv
|
||
|
sgemv
|
||
|
sger
|
||
|
ssbmv
|
||
|
sspr
|
||
|
sspr2
|
||
|
ssymv
|
||
|
ssyr
|
||
|
ssyr2
|
||
|
stbmv
|
||
|
stpsv
|
||
|
strmv
|
||
|
strsv
|
||
|
dgbmv
|
||
|
dgemv
|
||
|
dger
|
||
|
dsbmv
|
||
|
dspr
|
||
|
dspr2
|
||
|
dsymv
|
||
|
dsyr
|
||
|
dsyr2
|
||
|
dtbmv
|
||
|
dtpsv
|
||
|
dtrmv
|
||
|
dtrsv
|
||
|
cgbmv
|
||
|
cgemv
|
||
|
cgerc
|
||
|
cgeru
|
||
|
chbmv
|
||
|
chemv
|
||
|
cher
|
||
|
cher2
|
||
|
chpmv
|
||
|
chpr
|
||
|
chpr2
|
||
|
ctbmv
|
||
|
ctbsv
|
||
|
ctpmv
|
||
|
ctpsv
|
||
|
ctrmv
|
||
|
ctrsv
|
||
|
csyr
|
||
|
zgbmv
|
||
|
zgemv
|
||
|
zgerc
|
||
|
zgeru
|
||
|
zhbmv
|
||
|
zhemv
|
||
|
zher
|
||
|
zher2
|
||
|
zhpmv
|
||
|
zhpr
|
||
|
zhpr2
|
||
|
ztbmv
|
||
|
ztbsv
|
||
|
ztpmv
|
||
|
ztrmv
|
||
|
ztrsv
|
||
|
zsyr
|
||
|
|
||
|
BLAS Level 3 functions
|
||
|
----------------------
|
||
|
|
||
|
.. autosummary::
|
||
|
:toctree: generated/
|
||
|
|
||
|
sgemm
|
||
|
ssymm
|
||
|
ssyr2k
|
||
|
ssyrk
|
||
|
strmm
|
||
|
strsm
|
||
|
dgemm
|
||
|
dsymm
|
||
|
dsyr2k
|
||
|
dsyrk
|
||
|
dtrmm
|
||
|
dtrsm
|
||
|
cgemm
|
||
|
chemm
|
||
|
cher2k
|
||
|
cherk
|
||
|
csymm
|
||
|
csyr2k
|
||
|
csyrk
|
||
|
ctrmm
|
||
|
ctrsm
|
||
|
zgemm
|
||
|
zhemm
|
||
|
zher2k
|
||
|
zherk
|
||
|
zsymm
|
||
|
zsyr2k
|
||
|
zsyrk
|
||
|
ztrmm
|
||
|
ztrsm
|
||
|
|
||
|
"""
|
||
|
#
|
||
|
# Author: Pearu Peterson, March 2002
|
||
|
# refactoring by Fabian Pedregosa, March 2010
|
||
|
#
|
||
|
|
||
|
from __future__ import division, print_function, absolute_import
|
||
|
|
||
|
__all__ = ['get_blas_funcs', 'find_best_blas_type']
|
||
|
|
||
|
import numpy as _np
|
||
|
|
||
|
from scipy.linalg import _fblas
|
||
|
try:
|
||
|
from scipy.linalg import _cblas
|
||
|
except ImportError:
|
||
|
_cblas = None
|
||
|
|
||
|
# Expose all functions (only fblas --- cblas is an implementation detail)
|
||
|
empty_module = None
|
||
|
from scipy.linalg._fblas import *
|
||
|
del empty_module
|
||
|
|
||
|
# 'd' will be default for 'i',..
|
||
|
_type_conv = {'f': 's', 'd': 'd', 'F': 'c', 'D': 'z', 'G': 'z'}
|
||
|
|
||
|
# some convenience alias for complex functions
|
||
|
_blas_alias = {'cnrm2': 'scnrm2', 'znrm2': 'dznrm2',
|
||
|
'cdot': 'cdotc', 'zdot': 'zdotc',
|
||
|
'cger': 'cgerc', 'zger': 'zgerc',
|
||
|
'sdotc': 'sdot', 'sdotu': 'sdot',
|
||
|
'ddotc': 'ddot', 'ddotu': 'ddot'}
|
||
|
|
||
|
|
||
|
def find_best_blas_type(arrays=(), dtype=None):
|
||
|
"""Find best-matching BLAS/LAPACK type.
|
||
|
|
||
|
Arrays are used to determine the optimal prefix of BLAS routines.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
arrays : sequence of ndarrays, optional
|
||
|
Arrays can be given to determine optimal prefix of BLAS
|
||
|
routines. If not given, double-precision routines will be
|
||
|
used, otherwise the most generic type in arrays will be used.
|
||
|
dtype : str or dtype, optional
|
||
|
Data-type specifier. Not used if `arrays` is non-empty.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
prefix : str
|
||
|
BLAS/LAPACK prefix character.
|
||
|
dtype : dtype
|
||
|
Inferred Numpy data type.
|
||
|
prefer_fortran : bool
|
||
|
Whether to prefer Fortran order routines over C order.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> import scipy.linalg.blas as bla
|
||
|
>>> a = np.random.rand(10,15)
|
||
|
>>> b = np.asfortranarray(a) # Change the memory layout order
|
||
|
>>> bla.find_best_blas_type((a,))
|
||
|
('d', dtype('float64'), False)
|
||
|
>>> bla.find_best_blas_type((a*1j,))
|
||
|
('z', dtype('complex128'), False)
|
||
|
>>> bla.find_best_blas_type((b,))
|
||
|
('d', dtype('float64'), True)
|
||
|
|
||
|
"""
|
||
|
dtype = _np.dtype(dtype)
|
||
|
prefer_fortran = False
|
||
|
|
||
|
if arrays:
|
||
|
# use the most generic type in arrays
|
||
|
dtypes = [ar.dtype for ar in arrays]
|
||
|
dtype = _np.find_common_type(dtypes, ())
|
||
|
try:
|
||
|
index = dtypes.index(dtype)
|
||
|
except ValueError:
|
||
|
index = 0
|
||
|
if arrays[index].flags['FORTRAN']:
|
||
|
# prefer Fortran for leading array with column major order
|
||
|
prefer_fortran = True
|
||
|
|
||
|
prefix = _type_conv.get(dtype.char, 'd')
|
||
|
if dtype.char == 'G':
|
||
|
# complex256 -> complex128 (i.e., C long double -> C double)
|
||
|
dtype = _np.dtype('D')
|
||
|
elif dtype.char not in 'fdFD':
|
||
|
dtype = _np.dtype('d')
|
||
|
|
||
|
return prefix, dtype, prefer_fortran
|
||
|
|
||
|
|
||
|
def _get_funcs(names, arrays, dtype,
|
||
|
lib_name, fmodule, cmodule,
|
||
|
fmodule_name, cmodule_name, alias):
|
||
|
"""
|
||
|
Return available BLAS/LAPACK functions.
|
||
|
|
||
|
Used also in lapack.py. See get_blas_funcs for docstring.
|
||
|
"""
|
||
|
|
||
|
funcs = []
|
||
|
unpack = False
|
||
|
dtype = _np.dtype(dtype)
|
||
|
module1 = (cmodule, cmodule_name)
|
||
|
module2 = (fmodule, fmodule_name)
|
||
|
|
||
|
if isinstance(names, str):
|
||
|
names = (names,)
|
||
|
unpack = True
|
||
|
|
||
|
prefix, dtype, prefer_fortran = find_best_blas_type(arrays, dtype)
|
||
|
|
||
|
if prefer_fortran:
|
||
|
module1, module2 = module2, module1
|
||
|
|
||
|
for i, name in enumerate(names):
|
||
|
func_name = prefix + name
|
||
|
func_name = alias.get(func_name, func_name)
|
||
|
func = getattr(module1[0], func_name, None)
|
||
|
module_name = module1[1]
|
||
|
if func is None:
|
||
|
func = getattr(module2[0], func_name, None)
|
||
|
module_name = module2[1]
|
||
|
if func is None:
|
||
|
raise ValueError(
|
||
|
'%s function %s could not be found' % (lib_name, func_name))
|
||
|
func.module_name, func.typecode = module_name, prefix
|
||
|
func.dtype = dtype
|
||
|
func.prefix = prefix # Backward compatibility
|
||
|
funcs.append(func)
|
||
|
|
||
|
if unpack:
|
||
|
return funcs[0]
|
||
|
else:
|
||
|
return funcs
|
||
|
|
||
|
|
||
|
def get_blas_funcs(names, arrays=(), dtype=None):
|
||
|
"""Return available BLAS function objects from names.
|
||
|
|
||
|
Arrays are used to determine the optimal prefix of BLAS routines.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
names : str or sequence of str
|
||
|
Name(s) of BLAS functions without type prefix.
|
||
|
|
||
|
arrays : sequence of ndarrays, optional
|
||
|
Arrays can be given to determine optimal prefix of BLAS
|
||
|
routines. If not given, double-precision routines will be
|
||
|
used, otherwise the most generic type in arrays will be used.
|
||
|
|
||
|
dtype : str or dtype, optional
|
||
|
Data-type specifier. Not used if `arrays` is non-empty.
|
||
|
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
funcs : list
|
||
|
List containing the found function(s).
|
||
|
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
This routine automatically chooses between Fortran/C
|
||
|
interfaces. Fortran code is used whenever possible for arrays with
|
||
|
column major order. In all other cases, C code is preferred.
|
||
|
|
||
|
In BLAS, the naming convention is that all functions start with a
|
||
|
type prefix, which depends on the type of the principal
|
||
|
matrix. These can be one of {'s', 'd', 'c', 'z'} for the numpy
|
||
|
types {float32, float64, complex64, complex128} respectively.
|
||
|
The code and the dtype are stored in attributes `typecode` and `dtype`
|
||
|
of the returned functions.
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
>>> import scipy.linalg as LA
|
||
|
>>> a = np.random.rand(3,2)
|
||
|
>>> x_gemv = LA.get_blas_funcs('gemv', (a,))
|
||
|
>>> x_gemv.typecode
|
||
|
'd'
|
||
|
>>> x_gemv = LA.get_blas_funcs('gemv',(a*1j,))
|
||
|
>>> x_gemv.typecode
|
||
|
'z'
|
||
|
|
||
|
"""
|
||
|
return _get_funcs(names, arrays, dtype,
|
||
|
"BLAS", _fblas, _cblas, "fblas", "cblas",
|
||
|
_blas_alias)
|