(a_gpu, rcond=1e-15, lib='cusolver')
Moore-Penrose pseudoinverse.

    Compute the Moore-Penrose pseudoinverse of the specified matrix.

    Parameters
    ----------
    a_gpu : pycuda.gpuarray.GPUArray
        Input matrix of shape `(m, n)`.
    rcond : float
        Singular values smaller than `rcond`*max(singular_values)`
        are set to zero.
    lib : str
        Library to use. May be either 'cula' or 'cusolver' (default).

    Returns
    -------
    a_inv_gpu : pycuda.gpuarray.GPUArray
        Pseudoinverse of input matrix.

    Notes
    -----
    Double precision is only supported if the standard version of the
    CULA Dense toolkit is installed.

    This function destroys the contents of the input matrix.

    If the input matrix is square, the pseudoinverse uses less memory.

    Examples
    --------
    >>> import pycuda.driver as drv
    >>> import pycuda.gpuarray as gpuarray
    >>> import pycuda.autoinit
    >>> import numpy as np
    >>> import skcuda.linalg as linalg
    >>> linalg.init()
    >>> a = np.asarray(np.random.rand(8, 4), np.float32)
    >>> a_gpu = gpuarray.to_gpu(a)
    >>> a_inv_gpu = linalg.pinv(a_gpu)
    >>> np.allclose(np.linalg.pinv(a), a_inv_gpu.get(), 1e-4)
    True
    >>> b = np.asarray(np.random.rand(8, 4)+1j*np.random.rand(8, 4), np.complex64)
    >>> b_gpu = gpuarray.to_gpu(b)
    >>> b_inv_gpu = linalg.pinv(b_gpu)
    >>> np.allclose(np.linalg.pinv(b), b_inv_gpu.get(), 1e-4)
    True

    Notes
    -----
    The CUSOLVER backend cannot be used with CUDA 7.0.
Moore-Penrose pseudoinverse.
Moore - Penrose pseudoinverse .
def pinv(a_gpu, rcond=1e-15, lib='cusolver'):
    """
    Moore-Penrose pseudoinverse.

    Compute the Moore-Penrose pseudoinverse of the specified matrix.

    Parameters
    ----------
    a_gpu : pycuda.gpuarray.GPUArray
        Input matrix of shape `(m, n)`.
    rcond : float
        Singular values smaller than `rcond`*max(singular_values)`
        are set to zero.
    lib : str
        Library to use. May be either 'cula' or 'cusolver' (default).

    Returns
    -------
    a_inv_gpu : pycuda.gpuarray.GPUArray
        Pseudoinverse of input matrix.

    Notes
    -----
    Double precision is only supported if the standard version of the
    CULA Dense toolkit is installed.

    This function destroys the contents of the input matrix.

    If the input matrix is square, the pseudoinverse uses less memory.

    Examples
    --------
    >>> import pycuda.driver as drv
    >>> import pycuda.gpuarray as gpuarray
    >>> import pycuda.autoinit
    >>> import numpy as np
    >>> import skcuda.linalg as linalg
    >>> linalg.init()
    >>> a = np.asarray(np.random.rand(8, 4), np.float32)
    >>> a_gpu = gpuarray.to_gpu(a)
    >>> a_inv_gpu = linalg.pinv(a_gpu)
    >>> np.allclose(np.linalg.pinv(a), a_inv_gpu.get(), 1e-4)
    True
    >>> b = np.asarray(np.random.rand(8, 4)+1j*np.random.rand(8, 4), np.complex64)
    >>> b_gpu = gpuarray.to_gpu(b)
    >>> b_inv_gpu = linalg.pinv(b_gpu)
    >>> np.allclose(np.linalg.pinv(b), b_inv_gpu.get(), 1e-4)
    True

    Notes
    -----
    The CUSOLVER backend cannot be used with CUDA 7.0.
    """

    if lib == 'cula' and not _has_cula:
        raise NotImplementedError('CULA not installed')

    # Perform in-place SVD if the matrix is square to save memory:
    if a_gpu.shape[0] == a_gpu.shape[1]:
        u_gpu, s_gpu, vh_gpu = svd(a_gpu, 's', 'o', lib)
    else:
        u_gpu, s_gpu, vh_gpu = svd(a_gpu, 's', 's', lib)

    # Suppress very small singular values and convert the singular value array
    # to complex if the original matrix is complex so that the former can be
    # handled by dot_diag():
    cutoff_gpu = gpuarray.max(s_gpu)*rcond
    real_ctype = tools.dtype_to_ctype(s_gpu.dtype)
    if a_gpu.dtype in [np.complex64, np.complex128]:
        if s_gpu.dtype == np.float32:
            complex_dtype = np.complex64
        elif s_gpu.dtype == np.float64:
            complex_dtype = np.complex128
        else:
            raise ValueError('cannot convert singular values to complex')
        s_complex_gpu = gpuarray.empty(len(s_gpu), complex_dtype)
        complex_ctype = tools.dtype_to_ctype(complex_dtype)
        cutoff_func = el.ElementwiseKernel("{real_ctype} *s_real, {complex_ctype} *s_complex,"
            " {real_ctype} *cutoff".format(real_ctype=real_ctype, complex_ctype=complex_ctype),
            "if (s_real[i] > cutoff[0]) {s_complex[i] = 1/s_real[i];} else {s_complex[i] = 0;}")
        cutoff_func(s_gpu, s_complex_gpu, cutoff_gpu)

        # Compute the pseudoinverse without allocating a new diagonal matrix:
        return dot(vh_gpu, dot_diag(s_complex_gpu, u_gpu, 't'), 'c', 'c')

    else:
        cutoff_func = el.ElementwiseKernel("{real_ctype} *s, {real_ctype} *cutoff".format(real_ctype=real_ctype),
                                           "if (s[i] > cutoff[0]) {s[i] = 1/s[i];} else {s[i] = 0;}")
        cutoff_func(s_gpu, cutoff_gpu)

        # Compute the pseudoinverse without allocating a new diagonal matrix:
        return dot(vh_gpu, dot_diag(s_gpu, u_gpu, 't'), 'c', 'c')
def pinv ( a_gpu , rcond = 1e-15 , lib = 'cusolver' ) : if lib == 'cula' and not _has_cula : raise NotImplementedError ( 'CULA not installed' ) # Perform in-place SVD if the matrix is square to save memory: if a_gpu . shape [ 0 ] == a_gpu . shape [ 1 ] : u_gpu , s_gpu , vh_gpu = svd ( a_gpu , 's' , 'o' , lib ) else : u_gpu , s_gpu , vh_gpu = svd ( a_gpu , 's' , 's' , lib ) # Suppress very small singular values and convert the singular value array # to complex if the original matrix is complex so that the former can be # handled by dot_diag(): cutoff_gpu = gpuarray . max ( s_gpu ) * rcond real_ctype = tools . dtype_to_ctype ( s_gpu . dtype ) if a_gpu . dtype in [ np . complex64 , np . complex128 ] : if s_gpu . dtype == np . float32 : complex_dtype = np . complex64 elif s_gpu . dtype == np . float64 : complex_dtype = np . complex128 else : raise ValueError ( 'cannot convert singular values to complex' ) s_complex_gpu = gpuarray . empty ( len ( s_gpu ) , complex_dtype ) complex_ctype = tools . dtype_to_ctype ( complex_dtype ) cutoff_func = el . ElementwiseKernel ( "{real_ctype} *s_real, {complex_ctype} *s_complex," " {real_ctype} *cutoff" . format ( real_ctype = real_ctype , complex_ctype = complex_ctype ) , "if (s_real[i] > cutoff[0]) {s_complex[i] = 1/s_real[i];} else {s_complex[i] = 0;}" ) cutoff_func ( s_gpu , s_complex_gpu , cutoff_gpu ) # Compute the pseudoinverse without allocating a new diagonal matrix: return dot ( vh_gpu , dot_diag ( s_complex_gpu , u_gpu , 't' ) , 'c' , 'c' ) else : cutoff_func = el . ElementwiseKernel ( "{real_ctype} *s, {real_ctype} *cutoff" . format ( real_ctype = real_ctype ) , "if (s[i] > cutoff[0]) {s[i] = 1/s[i];} else {s[i] = 0;}" ) cutoff_func ( s_gpu , cutoff_gpu ) # Compute the pseudoinverse without allocating a new diagonal matrix: return dot ( vh_gpu , dot_diag ( s_gpu , u_gpu , 't' ) , 'c' , 'c' )