123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- """
- 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
- #
- __all__ = ['get_blas_funcs', 'find_best_blas_type']
- import numpy as _np
- import functools
- from scipy.linalg import _fblas
- try:
- from scipy.linalg import _cblas
- except ImportError:
- _cblas = None
- try:
- from scipy.linalg import _fblas_64
- HAS_ILP64 = True
- except ImportError:
- HAS_ILP64 = False
- _fblas_64 = None
- # Expose all functions (only fblas --- cblas is an implementation detail)
- empty_module = None
- from scipy.linalg._fblas import *
- del empty_module
- # all numeric dtypes '?bBhHiIlLqQefdgFDGO' that are safe to be converted to
- # single precision float : '?bBhH!!!!!!ef!!!!!!'
- # double precision float : '?bBhHiIlLqQefdg!!!!'
- # single precision complex : '?bBhH!!!!!!ef!!F!!!'
- # double precision complex : '?bBhHiIlLqQefdgFDG!'
- _type_score = {x: 1 for x in '?bBhHef'}
- _type_score.update({x: 2 for x in 'iIlLqQd'})
- # Handle float128(g) and complex256(G) separately in case non-Windows systems.
- # On Windows, the values will be rewritten to the same key with the same value.
- _type_score.update({'F': 3, 'D': 4, 'g': 2, 'G': 4})
- # Final mapping to the actual prefixes and dtypes
- _type_conv = {1: ('s', _np.dtype('float32')),
- 2: ('d', _np.dtype('float64')),
- 3: ('c', _np.dtype('complex64')),
- 4: ('z', _np.dtype('complex128'))}
- # 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 numpy as np
- >>> import scipy.linalg.blas as bla
- >>> rng = np.random.default_rng()
- >>> a = rng.random((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)
- max_score = _type_score.get(dtype.char, 5)
- prefer_fortran = False
- if arrays:
- # In most cases, single element is passed through, quicker route
- if len(arrays) == 1:
- max_score = _type_score.get(arrays[0].dtype.char, 5)
- prefer_fortran = arrays[0].flags['FORTRAN']
- else:
- # use the most generic type in arrays
- scores = [_type_score.get(x.dtype.char, 5) for x in arrays]
- max_score = max(scores)
- ind_max_score = scores.index(max_score)
- # safe upcasting for mix of float64 and complex64 --> prefix 'z'
- if max_score == 3 and (2 in scores):
- max_score = 4
- if arrays[ind_max_score].flags['FORTRAN']:
- # prefer Fortran for leading array with column major order
- prefer_fortran = True
- # Get the LAPACK prefix and the corresponding dtype if not fall back
- # to 'd' and double precision float.
- prefix, dtype = _type_conv.get(max_score, ('d', _np.dtype('float64')))
- return prefix, dtype, prefer_fortran
- def _get_funcs(names, arrays, dtype,
- lib_name, fmodule, cmodule,
- fmodule_name, cmodule_name, alias,
- ilp64=False):
- """
- 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 name in 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
- if not ilp64:
- func.int_dtype = _np.dtype(_np.intc)
- else:
- func.int_dtype = _np.dtype(_np.int64)
- func.prefix = prefix # Backward compatibility
- funcs.append(func)
- if unpack:
- return funcs[0]
- else:
- return funcs
- def _memoize_get_funcs(func):
- """
- Memoized fast path for _get_funcs instances
- """
- memo = {}
- func.memo = memo
- @functools.wraps(func)
- def getter(names, arrays=(), dtype=None, ilp64=False):
- key = (names, dtype, ilp64)
- for array in arrays:
- # cf. find_blas_funcs
- key += (array.dtype.char, array.flags.fortran)
- try:
- value = memo.get(key)
- except TypeError:
- # unhashable key etc.
- key = None
- value = None
- if value is not None:
- return value
- value = func(names, arrays, dtype, ilp64)
- if key is not None:
- memo[key] = value
- return value
- return getter
- @_memoize_get_funcs
- def get_blas_funcs(names, arrays=(), dtype=None, ilp64=False):
- """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.
- ilp64 : {True, False, 'preferred'}, optional
- Whether to return ILP64 routine variant.
- Choosing 'preferred' returns ILP64 routine if available,
- and otherwise the 32-bit routine. Default: False
- 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 numpy as np
- >>> import scipy.linalg as LA
- >>> rng = np.random.default_rng()
- >>> a = rng.random((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'
- """
- if isinstance(ilp64, str):
- if ilp64 == 'preferred':
- ilp64 = HAS_ILP64
- else:
- raise ValueError("Invalid value for 'ilp64'")
- if not ilp64:
- return _get_funcs(names, arrays, dtype,
- "BLAS", _fblas, _cblas, "fblas", "cblas",
- _blas_alias, ilp64=False)
- else:
- if not HAS_ILP64:
- raise RuntimeError("BLAS ILP64 routine requested, but Scipy "
- "compiled only with 32-bit BLAS")
- return _get_funcs(names, arrays, dtype,
- "BLAS", _fblas_64, None, "fblas_64", None,
- _blas_alias, ilp64=True)
|