Source code for arrayfire.lapack

#######################################################
# Copyright (c) 2015, ArrayFire
# All rights reserved.
#
# This file is distributed under 3-clause BSD license.
# The complete license agreement can be obtained at:
# http://arrayfire.com/licenses/BSD-3-Clause
########################################################

"""
Dense Linear Algebra functions (solve, inverse, etc).
"""

from .library import *
from .array import *

[docs]def lu(A): """ LU decomposition. Parameters ---------- A: af.Array A 2 dimensional arrayfire array. Returns ------- (L,U,P): tuple of af.Arrays - L - Lower triangular matrix. - U - Upper triangular matrix. - P - Permutation array. Note ---- The original matrix `A` can be reconstructed using the outputs in the following manner. >>> A[P, :] = af.matmul(L, U) """ L = Array() U = Array() P = Array() safe_call(backend.get().af_lu(ct.pointer(L.arr), ct.pointer(U.arr), ct.pointer(P.arr), A.arr)) return L,U,P
[docs]def lu_inplace(A, pivot="lapack"): """ In place LU decomposition. Parameters ---------- A: af.Array - a 2 dimensional arrayfire array on entry. - Contains L in the lower triangle on exit. - Contains U in the upper triangle on exit. Returns ------- P: af.Array - Permutation array. Note ---- This function is primarily used with `af.solve_lu` to reduce computations. """ P = Array() is_pivot_lapack = False if (pivot == "full") else True safe_call(backend.get().af_lu_inplace(ct.pointer(P.arr), A.arr, is_pivot_lapack)) return P
[docs]def qr(A): """ QR decomposition. Parameters ---------- A: af.Array A 2 dimensional arrayfire array. Returns ------- (Q,R,T): tuple of af.Arrays - Q - Orthogonal matrix. - R - Upper triangular matrix. - T - Vector containing additional information to solve a least squares problem. Note ---- The outputs of this funciton have the following properties. >>> A = af.matmul(Q, R) >>> I = af.matmulNT(Q, Q) # Identity matrix """ Q = Array() R = Array() T = Array() safe_call(backend.get().af_lu(ct.pointer(Q.arr), ct.pointer(R.arr), ct.pointer(T.arr), A.arr)) return Q,R,T
[docs]def qr_inplace(A): """ In place QR decomposition. Parameters ---------- A: af.Array - a 2 dimensional arrayfire array on entry. - Packed Q and R matrices on exit. Returns ------- T: af.Array - Vector containing additional information to solve a least squares problem. Note ---- This function is used to save space only when `R` is required. """ T = Array() safe_call(backend.get().af_qr_inplace(ct.pointer(T.arr), A.arr)) return T
[docs]def cholesky(A, is_upper=True): """ Cholesky decomposition Parameters ---------- A: af.Array A 2 dimensional, symmetric, positive definite matrix. is_upper: optional: bool. default: True Specifies if output `R` is upper triangular (if True) or lower triangular (if False). Returns ------- (R,info): tuple of af.Array, int. - R - triangular matrix. - info - 0 if decomposition sucessful. Note ---- The original matrix `A` can be reconstructed using the outputs in the following manner. >>> A = af.matmulNT(R, R) #if R is upper triangular """ R = Array() info = ct.c_int(0) safe_call(backend.get().af_cholesky(ct.pointer(R.arr), ct.pointer(info), A.arr, is_upper)) return R, info.value
[docs]def cholesky_inplace(A, is_upper=True): """ In place Cholesky decomposition. Parameters ---------- A: af.Array - a 2 dimensional, symmetric, positive definite matrix. - Trinangular matrix on exit. is_upper: optional: bool. default: True. Specifies if output `R` is upper triangular (if True) or lower triangular (if False). Returns ------- info : int. 0 if decomposition sucessful. """ info = ct.c_int(0) safe_call(backend.get().af_cholesky_inplace(ct.pointer(info), A.arr, is_upper)) return info.value
[docs]def solve(A, B, options=MATPROP.NONE): """ Solve a system of linear equations. Parameters ---------- A: af.Array A 2 dimensional arrayfire array representing the coefficients of the system. B: af.Array A 1 or 2 dimensional arrayfire array representing the constants of the system. options: optional: af.MATPROP. default: af.MATPROP.NONE. - Additional options to speed up computations. - Currently needs to be one of `af.MATPROP.NONE`, `af.MATPROP.LOWER`, `af.MATPROP.UPPER`. Returns ------- X: af.Array A 1 or 2 dimensional arrayfire array representing the unknowns in the system. """ X = Array() safe_call(backend.get().af_solve(ct.pointer(X.arr), A.arr, B.arr, options.value)) return X
[docs]def solve_lu(A, P, B, options=MATPROP.NONE): """ Solve a system of linear equations, using LU decomposition. Parameters ---------- A: af.Array - A 2 dimensional arrayfire array representing the coefficients of the system. - This matrix should be decomposed previously using `lu_inplace(A)`. P: af.Array - Permutation array. - This array is the output of an earlier call to `lu_inplace(A)` B: af.Array A 1 or 2 dimensional arrayfire array representing the constants of the system. Returns ------- X: af.Array A 1 or 2 dimensional arrayfire array representing the unknowns in the system. """ X = Array() safe_call(backend.get().af_solve_lu(ct.pointer(X.arr), A.arr, P.arr, B.arr, options.value)) return X
[docs]def inverse(A, options=MATPROP.NONE): """ Invert a matrix. Parameters ---------- A: af.Array - A 2 dimensional arrayfire array options: optional: af.MATPROP. default: af.MATPROP.NONE. - Additional options to speed up computations. - Currently needs to be one of `af.MATPROP.NONE`. Returns ------- AI: af.Array - A 2 dimensional array that is the inverse of `A` Note ---- `A` needs to be a square matrix. """ AI = Array() safe_call(backend.get().af_inverse(ct.pointer(AI.arr), A.arr, options.value)) return AI
[docs]def rank(A, tol=1E-5): """ Rank of a matrix. Parameters ---------- A: af.Array - A 2 dimensional arrayfire array tol: optional: scalar. default: 1E-5. - Tolerance for calculating rank Returns ------- r: int - Rank of `A` within the given tolerance """ r = ct.c_uint(0) safe_call(backend.get().af_rank(ct.pointer(r), A.arr, ct.c_double(tol))) return r.value
[docs]def det(A): """ Determinant of a matrix. Parameters ---------- A: af.Array - A 2 dimensional arrayfire array Returns ------- res: scalar - Determinant of the matrix. """ re = ct.c_double(0) im = ct.c_double(0) safe_call(backend.get().af_det(ct.pointer(re), ct.pointer(im), A.arr)) re = re.value im = im.value return re if (im == 0) else re + im * 1j
[docs]def norm(A, norm_type=NORM.EUCLID, p=1.0, q=1.0): """ Norm of an array or a matrix. Parameters ---------- A: af.Array - A 1 or 2 dimensional arrayfire array norm_type: optional: af.NORM. default: af.NORM.EUCLID. - Type of norm to be calculated. p: scalar. default 1.0. - Used only if `norm_type` is one of `af.NORM.VECTOR_P`, `af.NORM_MATRIX_L_PQ` q: scalar. default 1.0. - Used only if `norm_type` is `af.NORM_MATRIX_L_PQ` Returns ------- res: scalar - norm of the input """ res = ct.c_double(0) safe_call(backend.get().af_norm(ct.pointer(res), A.arr, norm_type.value, ct.c_double(p), ct.c_double(q))) return res.value
[docs]def svd(A): """ Singular Value Decomposition Parameters ---------- A: af.Array A 2 dimensional arrayfire array. Returns ------- (U,S,Vt): tuple of af.Arrays - U - A unitary matrix - S - An array containing the elements of diagonal matrix - Vt - A unitary matrix Note ---- - The original matrix `A` is preserved and additional storage space is required for decomposition. - If the original matrix `A` need not be preserved, use `svd_inplace` instead. - The original matrix `A` can be reconstructed using the outputs in the following manner. >>> Smat = af.diag(S, 0, False) >>> A_recon = af.matmul(af.matmul(U, Smat), Vt) """ U = Array() S = Array() Vt = Array() safe_call(backend.get().af_svd(ct.pointer(U.arr), ct.pointer(S.arr), ct.pointer(Vt.arr), A.arr)) return U, S, Vt
[docs]def svd_inplace(A): """ Singular Value Decomposition Parameters ---------- A: af.Array A 2 dimensional arrayfire array. Returns ------- (U,S,Vt): tuple of af.Arrays - U - A unitary matrix - S - An array containing the elements of diagonal matrix - Vt - A unitary matrix Note ---- - The original matrix `A` is not preserved. - If the original matrix `A` needs to be preserved, use `svd` instead. - The original matrix `A` can be reconstructed using the outputs in the following manner. >>> Smat = af.diag(S, 0, False) >>> A_recon = af.matmul(af.matmul(U, Smat), Vt) """ U = Array() S = Array() Vt = Array() safe_call(backend.get().af_svd_inplace(ct.pointer(U.arr), ct.pointer(S.arr), ct.pointer(Vt.arr), A.arr)) return U, S, Vt
[docs]def is_lapack_available(): """ Function to check if the arrayfire library was built with lapack support. """ res = ct.c_bool(False) safe_call(backend.get().af_is_lapack_available(ct.pointer(res))) return res.value