summaryrefslogtreecommitdiff
path: root/numpy/linalg/_gufuncs_linalg.py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/linalg/_gufuncs_linalg.py')
-rw-r--r--numpy/linalg/_gufuncs_linalg.py1371
1 files changed, 1371 insertions, 0 deletions
diff --git a/numpy/linalg/_gufuncs_linalg.py b/numpy/linalg/_gufuncs_linalg.py
new file mode 100644
index 000000000..3da399b1f
--- /dev/null
+++ b/numpy/linalg/_gufuncs_linalg.py
@@ -0,0 +1,1371 @@
+"""Linear Algebra functions implemented as gufuncs, so they broadcast.
+
+Notes
+-----
+
+.. warning:: This module is only for testing, the functionality will be
+ integrated into numpy.linalg proper.
+
+This module contains functionality that could be found in the linalg module,
+but in a gufunc-like way. This allows the use of vectorization and broadcasting
+on the operands.
+
+This module itself provides wrappers to kernels written as numpy
+generalized-ufuncs that perform the heavy-lifting of computation. The wrappers
+exist in order to provide a sane interface, like providing keyword arguments in
+line with the ones used by linalg, or just to automatically select the
+appropriate kernel depending on the parameters. All wrappers forward the
+keyword parameters to the underlying generalized ufunc (the kernel).
+
+The functions are intended to be used on arrays of matrices. Functions that in
+numpy.LinAlg would generate a LinAlgError (for example, inv on a non-invertible
+matrix) will just generate NaNs as result. When this happens, invalid floating
+point status will be set. Error handling can be configured for this cases using
+np.seterr.
+
+Additional functions some fused arithmetic, useful for efficient operation over
+"""
+
+from __future__ import division, absolute_import
+
+
+__all__ = ['inner1d', 'dotc1d', 'innerwt', 'matrix_multiply', 'det', 'slogdet',
+ 'inv', 'cholesky', 'quadratic_form', 'add3', 'multiply3',
+ 'multiply3_add', 'multiply_add', 'multiply_add2', 'multiply4',
+ 'multiply4_add', 'eig', 'eigvals', 'eigh', 'eigvalsh', 'solve',
+ 'svd', 'chosolve', 'poinv']
+
+import numpy as np
+
+from . import _umath_linalg as _impl
+
+
+def inner1d(a, b, **kwargs):
+ """
+ Compute the dot product of vectors over the inner dimension, with
+ broadcasting.
+
+ Parameters
+ ----------
+ a : (..., N) array
+ Input array
+ b : (..., N) array
+ Input array
+
+ Returns
+ -------
+ inner : (...) array
+ dot product over the inner dimension.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply when matching dimensions.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ For single and double types this is equivalent to dotc1d.
+
+ Maps to Blas functions sdot, ddot, cdotu and zdotu.
+
+ See Also
+ --------
+ dotc1d : dot product conjugating first vector.
+ innerwt : weighted (i.e. triple) inner product.
+
+ Examples
+ --------
+ >>> a = np.arange(1,5).reshape(2,2)
+ >>> b = np.arange(1,8,2).reshape(2,2)
+ >>> res = inner1d(a,b)
+ >>> res.shape
+ (2,)
+ >>> print res
+ [ 7. 43.]
+
+ """
+ return _impl.inner1d(a, b, **kwargs)
+
+
+def dotc1d(a, b, **kwargs):
+ """
+ Compute the dot product of vectors over the inner dimension, conjugating
+ the first vector, with broadcasting
+
+ Parameters
+ ----------
+ a : (..., N) array
+ Input array
+ b : (..., N) array
+ Input array
+
+ Returns
+ -------
+ dotc : (...) array
+ dot product conjugating the first vector over the inner
+ dimension.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply when matching dimensions.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ For single and double types this is equivalent to inner1d.
+
+ Maps to Blas functions sdot, ddot, cdotc and zdotc.
+
+ See Also
+ --------
+ inner1d : dot product
+ innerwt : weighted (i.e. triple) inner product.
+
+ Examples
+ --------
+ >>> a = np.arange(1,5).reshape(2,2)
+ >>> b = np.arange(1,8,2).reshape(2,2)
+ >>> res = inner1d(a,b)
+ >>> res.shape
+ (2,)
+ >>> print res
+ [ 7. 43.]
+
+ """
+ return _impl.dotc1d(a, b, **kwargs)
+
+
+def innerwt(a, b, c, **kwargs):
+ """
+ Compute the weighted (i.e. triple) inner product, with
+ broadcasting.
+
+ Parameters
+ ----------
+ a, b, c : (..., N) array
+ Input arrays
+
+ Returns
+ -------
+ inner : (...) array
+ The weighted (i.e. triple) inner product.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ inner1d : inner product.
+ dotc1d : dot product conjugating first vector.
+
+ Examples
+ --------
+ >>> a = np.arange(1,5).reshape(2,2)
+ >>> b = np.arange(1,8,2).reshape(2,2)
+ >>> c = np.arange(0.25,1.20,0.25).reshape(2,2)
+ >>> res = innerwt(a,b,c)
+ >>> res.shape
+ (2,)
+ >>> res
+ array([ 3.25, 39.25])
+
+ """
+ return _impl.innerwt(a, b, c, **kwargs)
+
+
+def matrix_multiply(a,b,**kwargs):
+ """
+ Compute matrix multiplication, with broadcasting
+
+ Parameters
+ ----------
+ a : (..., M, N) array
+ Input array.
+ b : (..., N, P) array
+ Input array.
+
+ Returns
+ -------
+ r : (..., M, P) array matrix multiplication of a and b over any number of
+ outer dimensions
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Matrix multiplication is computed using BLAS _gemm functions.
+
+ Implemented for single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ Examples
+ --------
+ >>> a = np.arange(1,17).reshape(2,2,4)
+ >>> b = np.arange(1,25).reshape(2,4,3)
+ >>> res = matrix_multiply(a,b)
+ >>> res.shape
+ (2, 2, 3)
+ >>> res
+ array([[[ 70., 80., 90.],
+ [ 158., 184., 210.]],
+ <BLANKLINE>
+ [[ 750., 792., 834.],
+ [ 1030., 1088., 1146.]]])
+
+ """
+ return _impl.matrix_multiply(a,b,**kwargs)
+
+
+def det(a, **kwargs):
+ """
+ Compute the determinant of arrays, with broadcasting.
+
+ Parameters
+ ----------
+ a : (NDIMS, M, M) array
+ Input array. Its inner dimensions must be those of a square 2-D array.
+
+ Returns
+ -------
+ det : (NDIMS) array
+ Determinants of `a`
+
+ See Also
+ --------
+ slogdet : Another representation for the determinant, more suitable
+ for large matrices where underflow/overflow may occur
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ The determinants are computed via LU factorization using the LAPACK
+ routine _getrf.
+
+ Implemented for single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ Examples
+ --------
+ The determinant of a 2-D array [[a, b], [c, d]] is ad - bc:
+
+ >>> a = np.array([[1, 2], [3, 4]])
+ >>> np.allclose(-2.0, det(a))
+ True
+
+ >>> a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]] ])
+ >>> np.allclose(-2.0, det(a))
+ True
+
+ """
+ return _impl.det(a, **kwargs)
+
+
+def slogdet(a, **kwargs):
+ """
+ Compute the sign and (natural) logarithm of the determinant of an array,
+ with broadcasting.
+
+ If an array has a very small or very large determinant, then a call to
+ `det` may overflow or underflow. This routine is more robust against such
+ issues, because it computes the logarithm of the determinant rather than
+ the determinant itself
+
+ Parameters
+ ----------
+ a : (..., M, M) array
+ Input array. Its inner dimensions must be those of a square 2-D array.
+
+ Returns
+ -------
+ sign : (...) array
+ An array of numbers representing the sign of the determinants. For real
+ matrices, this is 1, 0, or -1. For complex matrices, this is a complex
+ number with absolute value 1 (i.e., it is on the unit circle), or else
+ 0.
+ logdet : (...) array
+ The natural log of the absolute value of the determinant. This is always
+ a real type.
+
+ If the determinant is zero, then `sign` will be 0 and `logdet` will be -Inf.
+ In all cases, the determinant is equal to ``sign * np.exp(logdet)``.
+
+ See Also
+ --------
+ det
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ The determinants are computed via LU factorization using the LAPACK
+ routine _getrf.
+
+ Implemented for types single, double, csingle and cdouble. Numpy conversion
+ rules apply. For complex versions `logdet` will be of the associated real
+ type (single for csingle, double for cdouble).
+
+ Examples
+ --------
+ The determinant of a 2-D array [[a, b], [c, d]] is ad - bc:
+
+ >>> a = np.array([[1, 2], [3, 4]])
+ >>> (sign, logdet) = slogdet(a)
+ >>> sign.shape
+ ()
+ >>> logdet.shape
+ ()
+ >>> np.allclose(-2.0, sign * np.exp(logdet))
+ True
+
+ >>> a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]] ])
+ >>> (sign, logdet) = slogdet(a)
+ >>> sign.shape
+ (2,)
+ >>> logdet.shape
+ (2,)
+ >>> np.allclose(-2.0, sign * np.exp(logdet))
+ True
+
+ """
+ return _impl.slogdet(a, **kwargs)
+
+
+def inv(a, **kwargs):
+ """
+ Compute the (multiplicative) inverse of matrices, with broadcasting.
+
+ Given a square matrix `a`, return the matrix `ainv` satisfying
+ ``matrix_multiply(a, ainv) = matrix_multiply(ainv, a) = Identity matrix``
+
+ Parameters
+ ----------
+ a : (..., M, M) array
+ Matrices to be inverted
+
+ Returns
+ -------
+ ainv : (..., M, M) array
+ (Multiplicative) inverse of the `a` matrices.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ Singular matrices and thus, not invertible, result in an array of NaNs.
+
+ See Also
+ --------
+ poinv : compute the multiplicative inverse of hermitian/symmetric matrices,
+ using cholesky decomposition.
+
+ Examples
+ --------
+ >>> a = np.array([[1, 2], [3, 4]])
+ >>> ainv = inv(a)
+ >>> np.allclose(matrix_multiply(a, ainv), np.eye(2))
+ True
+ >>> np.allclose(matrix_multiply(ainv, a), np.eye(2))
+ True
+
+ """
+ return _impl.inv(a, **kwargs)
+
+
+def cholesky(a, UPLO='L', **kwargs):
+ """
+ Compute the cholesky decomposition of `a`, with broadcasting
+
+ The Cholesky decomposition (or Cholesky triangle) is a decomposition of a
+ Hermitian, positive-definite matrix into the product of a lower triangular
+ matrix and its conjugate transpose.
+
+ A = LL*
+
+ where L* is the positive-definite matrix.
+
+ Parameters
+ ----------
+ a : (..., M, M) array
+ Matrices for which compute the cholesky decomposition
+
+ Returns
+ -------
+ l : (..., M, M) array
+ Matrices for each element where each entry is the lower triangular
+ matrix with strictly positive diagonal entries such that a = ll* for
+ all outer dimensions
+
+ See Also
+ --------
+ chosolve : solve a system using cholesky decomposition
+ poinv : compute the inverse of a matrix using cholesky decomposition
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ Decomposition is performed using LAPACK routine _potrf.
+
+ For elements where the LAPACK routine fails, the result will be set to NaNs.
+
+ If an element of the source array is not a positive-definite matrix the
+ result for that element is undefined.
+
+ Examples
+ --------
+ >>> A = np.array([[1,-2j],[2j,5]])
+ >>> A
+ array([[ 1.+0.j, 0.-2.j],
+ [ 0.+2.j, 5.+0.j]])
+ >>> L = cholesky(A)
+ >>> L
+ array([[ 1.+0.j, 0.+0.j],
+ [ 0.+2.j, 1.+0.j]])
+
+ """
+ if 'L' == UPLO:
+ gufunc = _impl.cholesky_lo
+ else:
+ gufunc = _impl.cholesky_up
+
+ return gufunc(a, **kwargs)
+
+
+def eig(a, **kwargs):
+ """
+ Compute the eigenvalues and right eigenvectors of square arrays,
+ with broadcasting
+
+ Parameters
+ ----------
+ a : (..., M, M) array
+ Matrices for which the eigenvalues and right eigenvectors will
+ be computed
+
+ Returns
+ -------
+ w : (..., M) array
+ The eigenvalues, each repeated according to its multiplicity.
+ The eigenvalues are not necessarily ordered. The resulting
+ array will be always be of complex type. When `a` is real
+ the resulting eigenvalues will be real (0 imaginary part) or
+ occur in conjugate pairs
+
+ v : (..., M, M) array
+ The normalized (unit "length") eigenvectors, such that the
+ column ``v[:,i]`` is the eigenvector corresponding to the
+ eigenvalue ``w[i]``.
+
+ See Also
+ --------
+ eigvals : eigenvalues of general arrays.
+ eigh : eigenvalues and right eigenvectors of symmetric/hermitian
+ arrays.
+ eigvalsh : eigenvalues of symmetric/hermitian arrays.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ Eigenvalues and eigenvectors for single and double versions will
+ always be typed csingle and cdouble, even if all the results are
+ real (imaginary part will be 0).
+
+ This is implemented using the _geev LAPACK routines which compute
+ the eigenvalues and eigenvectors of general square arrays.
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Examples
+ --------
+ First, a utility function to check if eigvals/eigvectors are correct.
+ This checks the definition of eigenvectors. For each eigenvector v
+ with associated eigenvalue w of a matrix M the following equality must
+ hold: Mv == wv
+
+ >>> def check_eigen(M, w, v):
+ ... '''vectorial check of Mv==wv'''
+ ... lhs = matrix_multiply(M, v)
+ ... rhs = w*v
+ ... return np.allclose(lhs, rhs)
+
+ (Almost) Trivial example with real e-values and e-vectors. Note
+ the complex types of the results
+
+ >>> M = np.diag((1,2,3)).astype(float)
+ >>> w, v = eig(M)
+ >>> check_eigen(M, w, v)
+ True
+
+ Real matrix possessing complex e-values and e-vectors; note that the
+ e-values are complex conjugates of each other.
+
+ >>> M = np.array([[1, -1], [1, 1]])
+ >>> w, v = eig(M)
+ >>> check_eigen(M, w, v)
+ True
+
+ Complex-valued matrix with real e-values (but complex-valued e-vectors);
+ note that a.conj().T = a, i.e., a is Hermitian.
+
+ >>> M = np.array([[1, 1j], [-1j, 1]])
+ >>> w, v = eig(M)
+ >>> check_eigen(M, w, v)
+ True
+
+ """
+ return _impl.eig(a, **kwargs)
+
+
+def eigvals(a, **kwargs):
+ """
+ Compute the eigenvalues of general matrices, with broadcasting.
+
+ Main difference between `eigvals` and `eig`: the eigenvectors aren't
+ returned.
+
+ Parameters
+ ----------
+ a : (..., M, M) array
+ Matrices whose eigenvalues will be computed
+
+ Returns
+ -------
+ w : (..., M) array
+ The eigenvalues, each repeated according to its multiplicity.
+ The eigenvalues are not necessarily ordered. The resulting
+ array will be always be of complex type. When `a` is real
+ the resulting eigenvalues will be real (0 imaginary part) or
+ occur in conjugate pairs
+
+ See Also
+ --------
+ eig : eigenvalues and right eigenvectors of general arrays.
+ eigh : eigenvalues and right eigenvectors of symmetric/hermitian
+ arrays.
+ eigvalsh : eigenvalues of symmetric/hermitian arrays.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ Eigenvalues for single and double versions will always be typed
+ csingle and cdouble, even if all the results are real (imaginary
+ part will be 0).
+
+ This is implemented using the _geev LAPACK routines which compute
+ the eigenvalues and eigenvectors of general square arrays.
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Examples
+ --------
+
+ Eigenvalues for a diagonal matrix are its diagonal elements
+
+ >>> D = np.diag((-1,1))
+ >>> eigvals(D)
+ array([-1.+0.j, 1.+0.j])
+
+ Multiplying on the left by an orthogonal matrix, `Q`, and on the
+ right by `Q.T` (the transpose of `Q` preserves the eigenvalues of
+ the original matrix
+
+ >>> x = np.random.random()
+ >>> Q = np.array([[np.cos(x), -np.sin(x)], [np.sin(x), np.cos(x)]])
+ >>> A = matrix_multiply(Q, D)
+ >>> A = matrix_multiply(A, Q.T)
+ >>> eigvals(A)
+ array([-1.+0.j, 1.+0.j])
+
+ """
+ return _impl.eigvals(a, **kwargs)
+
+
+def quadratic_form(u,Q,v, **kwargs):
+ """
+ Compute the quadratic form uQv, with broadcasting
+
+ Parameters
+ ----------
+ u : (..., M) array
+ The u vectors of the quadratic form uQv
+
+ Q : (..., M, N) array
+ The Q matrices of the quadratic form uQv
+
+ v : (..., N) array
+ The v vectors of the quadratic form uQv
+
+ Returns
+ -------
+ qf : (...) array
+ The result of the quadratic forms
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ This is similar to PDL inner2
+
+ Examples
+ --------
+
+ The result in absence of broadcasting is just as np.dot(np.dot(u,Q),v)
+ or np.dot(u, np.dot(Q,v))
+
+ >>> u = np.array([2., 3.])
+ >>> Q = np.array([[1.,1.], [0.,1.]])
+ >>> v = np.array([1.,2.])
+ >>> quadratic_form(u,Q,v)
+ 12.0
+
+ >>> np.dot(np.dot(u,Q),v)
+ 12.0
+
+ >>> np.dot(u, np.dot(Q,v))
+ 12.0
+
+ """
+ return _impl.quadratic_form(u, Q, v, **kwargs)
+
+
+def add3(a, b, c, **kwargs):
+ """
+ Element-wise addition of 3 arrays: a + b + c.
+
+ Parameters
+ ----------
+ a, b, c : (...) array
+ arrays with the addends
+
+ Returns
+ -------
+ add3 : (...) array
+ resulting element-wise addition.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ multiply3 : element-wise three-way multiplication.
+ multiply3_add : element-wise three-way multiplication and addition.
+ multiply_add : element-wise multiply-add.
+ multiply_add2 : element-wise multiplication with two additions.
+ multiply4 : element-wise four-way multiplication
+ multiply4_add : element-wise four-way multiplication and addition,
+
+ Examples
+ --------
+ >>> a = np.linspace(1.0, 30.0, 30)
+ >>> add3(a[0::3], a[1::3], a[2::3])
+ array([ 6., 15., 24., 33., 42., 51., 60., 69., 78., 87.])
+
+ """
+ return _impl.add3(a, b, c, **kwargs)
+
+
+def multiply3(a, b, c, **kwargs):
+ """
+ Element-wise multiplication of 3 arrays: a*b*c.
+
+ Parameters
+ ----------
+ a, b, c : (...) array
+ arrays with the factors
+
+ Returns
+ -------
+ m3 : (...) array
+ resulting element-wise product
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ add3 : element-wise three-was addition
+ multiply3_add : element-wise three-way multiplication and addition.
+ multiply_add : element-wise multiply-add.
+ multiply_add2 : element-wise multiplication with two additions.
+ multiply4 : element-wise four-way multiplication
+ multiply4_add : element-wise four-way multiplication and addition,
+
+ Examples
+ --------
+ >>> a = np.linspace(1.0, 10.0, 10)
+ >>> multiply3(a, 1.01, a)
+ array([ 1.01, 4.04, 9.09, 16.16, 25.25, 36.36, 49.49,
+ 64.64, 81.81, 101. ])
+
+ """
+ return _impl.multiply3(a, b, c, **kwargs)
+
+
+def multiply3_add(a, b, c, d, **kwargs):
+ """
+ Element-wise multiplication of 3 arrays adding an element
+ of the a 4th array to the result: a*b*c + d
+
+ Parameters
+ ----------
+ a, b, c : (...) array
+ arrays with the factors
+
+ d : (...) array
+ array with the addend
+
+ Returns
+ -------
+ m3a : (...) array
+ resulting element-wise addition
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ add3 : element-wise three-was addition
+ multiply3 : element-wise three-way multiplication.
+ multiply3_add : element-wise three-way multiplication and addition.
+ multiply_add : element-wise multiply-add.
+ multiply_add2 : element-wise multiplication with two additions.
+ multiply4 : element-wise four-way multiplication
+ multiply4_add : element-wise four-way multiplication and addition,
+
+ Examples
+ --------
+ >>> a = np.linspace(1.0, 10.0, 10)
+ >>> multiply3_add(a, 1.01, a, 42e-4)
+ array([ 1.0142, 4.0442, 9.0942, 16.1642, 25.2542, 36.3642,
+ 49.4942, 64.6442, 81.8142, 101.0042])
+
+ """
+ return _impl.multiply3_add(a, b, c, d, **kwargs)
+
+
+def multiply_add(a, b, c, **kwargs):
+ """
+ Element-wise addition of 3 arrays
+
+ Parameters
+ ----------
+ a, b, c : (...) array
+ arrays with the addends
+
+ Returns
+ -------
+ add3 : (...) array
+ resulting element-wise addition
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ add3 : element-wise three-was addition
+ multiply3 : element-wise three-way multiplication.
+ multiply3_add : element-wise three-way multiplication and addition.
+ multiply_add : element-wise multiply-add.
+ multiply_add2 : element-wise multiplication with two additions.
+ multiply4 : element-wise four-way multiplication
+ multiply4_add : element-wise four-way multiplication and addition,
+
+ Examples
+ --------
+ >>> a = np.linspace(1.0, 10.0, 10)
+ >>> multiply_add(a, a, 42e-4)
+ array([ 1.0042, 4.0042, 9.0042, 16.0042, 25.0042, 36.0042,
+ 49.0042, 64.0042, 81.0042, 100.0042])
+
+ """
+ return _impl.multiply_add(a, b, c, **kwargs)
+
+
+def multiply_add2(a, b, c, d, **kwargs):
+ """
+ Element-wise addition of 3 arrays
+
+ Parameters
+ ----------
+ a, b, c : (...) array
+ arrays with the addends
+
+ Returns
+ -------
+ add3 : (...) array
+ resulting element-wise addition
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ add3 : element-wise three-was addition
+ multiply3 : element-wise three-way multiplication.
+ multiply3_add : element-wise three-way multiplication and addition.
+ multiply_add : element-wise multiply-add.
+ multiply_add2 : element-wise multiplication with two additions.
+ multiply4 : element-wise four-way multiplication
+ multiply4_add : element-wise four-way multiplication and addition,
+
+ Examples
+ --------
+ >>> a = np.linspace(1.0, 10.0, 10)
+ >>> multiply_add2(a, a, a, 42e-4)
+ array([ 2.0042, 6.0042, 12.0042, 20.0042, 30.0042, 42.0042,
+ 56.0042, 72.0042, 90.0042, 110.0042])
+
+ """
+ return _impl.multiply_add2(a, b, c, d, **kwargs)
+
+
+def multiply4(a, b, c, d, **kwargs):
+ """
+ Element-wise addition of 3 arrays
+
+ Parameters
+ ----------
+ a, b, c : (...) array
+ arrays with the addends
+
+ Returns
+ -------
+ add3 : (...) array
+ resulting element-wise addition
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ add3 : element-wise three-was addition
+ multiply3 : element-wise three-way multiplication.
+ multiply3_add : element-wise three-way multiplication and addition.
+ multiply_add : element-wise multiply-add.
+ multiply_add2 : element-wise multiplication with two additions.
+ multiply4 : element-wise four-way multiplication
+ multiply4_add : element-wise four-way multiplication and addition,
+
+ Examples
+ --------
+ >>> a = np.linspace(1.0, 10.0, 10)
+ >>> multiply4(a, a, a[::-1], 1.0001)
+ array([ 10.001 , 36.0036, 72.0072, 112.0112, 150.015 , 180.018 ,
+ 196.0196, 192.0192, 162.0162, 100.01 ])
+
+ """
+ return _impl.multiply4(a, b, c, d, **kwargs)
+
+
+def multiply4_add(a, b, c, d, e, **kwargs):
+ """
+ Element-wise addition of 3 arrays
+
+ Parameters
+ ----------
+ a, b, c : (...) array
+ arrays with the addends
+
+ Returns
+ -------
+ add3 : (...) array
+ resulting element-wise addition
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Implemented for types single, double, csingle and cdouble. Numpy
+ conversion rules apply.
+
+ See Also
+ --------
+ add3 : element-wise three-was addition
+ multiply3 : element-wise three-way multiplication.
+ multiply3_add : element-wise three-way multiplication and addition.
+ multiply_add : element-wise multiply-add.
+ multiply_add2 : element-wise multiplication with two additions.
+ multiply4 : element-wise four-way multiplication
+ multiply4_add : element-wise four-way multiplication and addition,
+
+ Examples
+ --------
+ >>> a = np.linspace(1.0, 10.0, 10)
+ >>> multiply4_add(a, a, a[::-1], 1.01, 42e-4)
+ array([ 10.1042, 36.3642, 72.7242, 113.1242, 151.5042, 181.8042,
+ 197.9642, 193.9242, 163.6242, 101.0042])
+
+ """
+ return _impl.multiply4_add(a, b, c, d, e,**kwargs)
+
+
+def eigh(A, UPLO='L', **kw_args):
+ """
+ Computes the eigenvalues and eigenvectors for the square matrices
+ in the inner dimensions of A, being those matrices
+ symmetric/hermitian.
+
+ Parameters
+ ----------
+ A : (..., M, M) array
+ Hermitian/Symmetric matrices whose eigenvalues and
+ eigenvectors are to be computed.
+ UPLO : {'L', 'U'}, optional
+ Specifies whether the calculation is done with the lower
+ triangular part of the elements in `A` ('L', default) or
+ the upper triangular part ('U').
+
+ Returns
+ -------
+ w : (..., M) array
+ The eigenvalues, not necessarily ordered.
+ v : (..., M, M) array
+ The inner dimensions contain matrices with the normalized
+ eigenvectors as columns. The column-numbers are coherent with
+ the associated eigenvalue.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ The eigenvalues/eigenvectors are computed using LAPACK routines _ssyevd,
+ _heevd
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Implemented for single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ Unlike eig, the results for single and double will always be single
+ and doubles. It is not possible for symmetrical real matrices to result
+ in complex eigenvalues/eigenvectors
+
+ See Also
+ --------
+ eigvalsh : eigenvalues of symmetric/hermitian arrays.
+ eig : eigenvalues and right eigenvectors for general matrices.
+ eigvals : eigenvalues for general matrices.
+
+ Examples
+ --------
+ First, a utility function to check if eigvals/eigvectors are correct.
+ This checks the definition of eigenvectors. For each eigenvector v
+ with associated eigenvalue w of a matrix M the following equality must
+ hold: Mv == wv
+
+ >>> def check_eigen(M, w, v):
+ ... '''vectorial check of Mv==wv'''
+ ... lhs = matrix_multiply(M, v)
+ ... rhs = w*v
+ ... return np.allclose(lhs, rhs)
+
+ A simple example that computes eigenvectors and eigenvalues of
+ a hermitian matrix and checks that A*v = v*w for both pairs of
+ eignvalues(w) and eigenvectors(v)
+
+ >>> M = np.array([[1, -2j], [2j, 1]])
+ >>> w, v = eigh(M)
+ >>> check_eigen(M, w, v)
+ True
+
+ """
+ if 'L' == UPLO:
+ gufunc = _impl.eigh_lo
+ else:
+ gufunc = _impl.eigh_up
+
+ return gufunc(A, **kw_args)
+
+
+def eigvalsh(A, UPLO='L', **kw_args):
+ """
+ Computes the eigenvalues for the square matrices in the inner
+ dimensions of A, being those matrices symmetric/hermitian.
+
+ Parameters
+ ----------
+ A : (..., M, M) array
+ Hermitian/Symmetric matrices whose eigenvalues and
+ eigenvectors are to be computed.
+ UPLO : {'L', 'U'}, optional
+ Specifies whether the calculation is done with the lower
+ triangular part of the elements in `A` ('L', default) or
+ the upper triangular part ('U').
+
+ Returns
+ -------
+ w : (..., M) array
+ The eigenvalues, not necessarily ordered.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ The eigenvalues are computed using LAPACK routines _ssyevd, _heevd
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Implemented for single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ Unlike eigvals, the results for single and double will always be single
+ and doubles. It is not possible for symmetrical real matrices to result
+ in complex eigenvalues.
+
+ See Also
+ --------
+ eigh : eigenvalues of symmetric/hermitian arrays.
+ eig : eigenvalues and right eigenvectors for general matrices.
+ eigvals : eigenvalues for general matrices.
+
+ Examples
+ --------
+ eigvalsh results should be the same as the eigenvalues returned by eigh
+
+ >>> a = np.array([[1, -2j], [2j, 5]])
+ >>> w, v = eigh(a)
+ >>> np.allclose(w, eigvalsh(a))
+ True
+
+ eigvalsh on an identity matrix is all ones
+ >>> eigvalsh(np.eye(6))
+ array([ 1., 1., 1., 1., 1., 1.])
+
+ """
+ if ('L' == UPLO):
+ gufunc = _impl.eigvalsh_lo
+ else:
+ gufunc = _impl.eigvalsh_up
+
+ return gufunc(A,**kw_args)
+
+
+def solve(A,B,**kw_args):
+ """
+ Solve the linear matrix equations on the inner dimensions.
+
+ Computes the "exact" solution, `x`. of the well-determined,
+ i.e., full rank, linear matrix equations `ax = b`.
+
+ Parameters
+ ----------
+ A : (..., M, M) array
+ Coefficient matrices.
+ B : (..., M, N) array
+ Ordinate or "dependent variable" values.
+
+ Returns
+ -------
+ X : (..., M, N) array
+ Solutions to the system A X = B for all the outer dimensions
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ The solutions are computed using LAPACK routine _gesv
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Implemented for single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ See Also
+ --------
+ chosolve : solve a system using cholesky decomposition (for equations
+ having symmetric/hermitian coefficient matrices)
+
+ Examples
+ --------
+ Solve the system of equations ``3 * x0 + x1 = 9`` and ``x0 + 2 * x1 = 8``:
+
+ >>> a = np.array([[3,1], [1,2]])
+ >>> b = np.array([9,8])
+ >>> x = solve(a, b)
+ >>> x
+ array([ 2., 3.])
+
+ Check that the solution is correct:
+
+ >>> np.allclose(np.dot(a, x), b)
+ True
+
+ """
+ if len(B.shape) == (len(A.shape) - 1):
+ gufunc = _impl.solve1
+ else:
+ gufunc = _impl.solve
+
+ return gufunc(A,B,**kw_args)
+
+
+def svd(a, full_matrices=1, compute_uv=1 ,**kw_args):
+ """
+ Singular Value Decomposition on the inner dimensions.
+
+ Factors the matrices in `a` as ``u * np.diag(s) * v``, where `u`
+ and `v` are unitary and `s` is a 1-d array of `a`'s singular
+ values.
+
+ Parameters
+ ----------
+ a : (..., M, N) array
+ The array of matrices to decompose.
+ full_matrices : bool, optional
+ If True (default), `u` and `v` have the shapes (`M`, `M`) and
+ (`N`, `N`), respectively. Otherwise, the shapes are (`M`, `K`)
+ and (`K`, `N`), respectively, where `K` = min(`M`, `N`).
+ compute_uv : bool, optional
+ Whether or not to compute `u` and `v` in addition to `s`. True
+ by default.
+
+ Returns
+ -------
+ u : { (..., M, M), (..., M, K) } array
+ Unitary matrices. The actual shape depends on the value of
+ ``full_matrices``. Only returned when ``compute_uv`` is True.
+ s : (..., K) array
+ The singular values for every matrix, sorted in descending order.
+ v : { (..., N, N), (..., K, N) } array
+ Unitary matrices. The actual shape depends on the value of
+ ``full_matrices``. Only returned when ``compute_uv`` is True.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ Singular Value Decomposition is performed using LAPACK routine _gesdd
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Implemented for types single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ Examples
+ --------
+ >>> a = np.random.randn(9, 6) + 1j*np.random.randn(9, 6)
+
+ Reconstruction based on full SVD:
+
+ >>> U, s, V = svd(a, full_matrices=True)
+ >>> U.shape, V.shape, s.shape
+ ((9, 9), (6, 6), (6,))
+ >>> S = np.zeros((9, 6), dtype=complex)
+ >>> S[:6, :6] = np.diag(s)
+ >>> np.allclose(a, np.dot(U, np.dot(S, V)))
+ True
+
+ Reconstruction based on reduced SVD:
+
+ >>> U, s, V = svd(a, full_matrices=False)
+ >>> U.shape, V.shape, s.shape
+ ((9, 6), (6, 6), (6,))
+ >>> S = np.diag(s)
+ >>> np.allclose(a, np.dot(U, np.dot(S, V)))
+ True
+
+ """
+ m = a.shape[-2]
+ n = a.shape[-1]
+ if 1 == compute_uv:
+ if 1 == full_matrices:
+ if m < n:
+ gufunc = _impl.svd_m_f
+ else:
+ gufunc = _impl.svd_n_f
+ else:
+ if m < n:
+ gufunc = _impl.svd_m_s
+ else:
+ gufunc = _impl.svd_n_s
+ else:
+ if m < n:
+ gufunc = _impl.svd_m
+ else:
+ gufunc = _impl.svd_n
+ return gufunc(a, **kw_args)
+
+
+def chosolve(A, B, UPLO='L', **kw_args):
+ """
+ Solve the linear matrix equations on the inner dimensions, using
+ cholesky decomposition.
+
+ Computes the "exact" solution, `x`. of the well-determined,
+ i.e., full rank, linear matrix equations `ax = b`, where a is
+ a symmetric/hermitian positive-definite matrix.
+
+ Parameters
+ ----------
+ A : (..., M, M) array
+ Coefficient symmetric/hermitian positive-definite matrices.
+ B : (..., M, N) array
+ Ordinate or "dependent variable" values.
+ UPLO : {'L', 'U'}, optional
+ Specifies whether the calculation is done with the lower
+ triangular part of the elements in `A` ('L', default) or
+ the upper triangular part ('U').
+
+ Returns
+ -------
+ X : (..., M, N) array
+ Solutions to the system A X = B for all elements in the outer
+ dimensions
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ The solutions are computed using LAPACK routines _potrf, _potrs
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Implemented for single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ See Also
+ --------
+ solve : solve a system using cholesky decomposition (for equations
+ having symmetric/hermitian coefficient matrices)
+
+ Examples
+ --------
+ Solve the system of equations ``3 * x0 + x1 = 9`` and ``x0 + 2 * x1 = 8``:
+ (note the matrix is symmetric in this system)
+
+ >>> a = np.array([[3,1], [1,2]])
+ >>> b = np.array([9,8])
+ >>> x = solve(a, b)
+ >>> x
+ array([ 2., 3.])
+
+ Check that the solution is correct:
+
+ >>> np.allclose(np.dot(a, x), b)
+ True
+
+ """
+ if len(B.shape) == (len(A.shape) - 1):
+ if 'L' == UPLO:
+ gufunc = _impl.chosolve1_lo
+ else:
+ gufunc = _impl.chosolve1_up
+ else:
+ if 'L' == UPLO:
+ gufunc = _impl.chosolve_lo
+ else:
+ gufunc = _impl.chosolve_up
+
+ return gufunc(A, B, **kw_args)
+
+
+def poinv(A, UPLO='L', **kw_args):
+ """
+ Compute the (multiplicative) inverse of symmetric/hermitian positive
+ definite matrices, with broadcasting.
+
+ Given a square symmetic/hermitian positive-definite matrix `a`, return
+ the matrix `ainv` satisfying ``matrix_multiply(a, ainv) =
+ matrix_multiply(ainv, a) = Identity matrix``.
+
+ Parameters
+ ----------
+ a : (..., M, M) array
+ Symmetric/hermitian postive definite matrices to be inverted.
+
+ Returns
+ -------
+ ainv : (..., M, M) array
+ (Multiplicative) inverse of the `a` matrices.
+
+ Notes
+ -----
+ Numpy broadcasting rules apply.
+
+ The inverse is computed using LAPACK routines _potrf, _potri
+
+ For elements where the LAPACK routine fails, the result will be set
+ to NaNs.
+
+ Implemented for types single, double, csingle and cdouble. Numpy conversion
+ rules apply.
+
+ See Also
+ --------
+ inv : compute the multiplicative inverse of general matrices.
+
+ Examples
+ --------
+ >>> a = np.array([[5, 3], [3, 5]])
+ >>> ainv = poinv(a)
+ >>> np.allclose(matrix_multiply(a, ainv), np.eye(2))
+ True
+ >>> np.allclose(matrix_multiply(ainv, a), np.eye(2))
+ True
+
+ """
+ if 'L' == UPLO:
+ gufunc = _impl.poinv_lo
+ else:
+ gufunc = _impl.poinv_up
+
+ return gufunc(A, **kw_args);
+
+
+if __name__ == "__main__":
+ import doctest
+ print "Running doctests..."
+ doctest.testmod()