001: /* ///////////////////////////// P /// L /// A /// S /// M /// A /////////////////////////////// */
002: /* ///                    PLASMA computational routine (version 2.0.0)                       ///
003:  * ///                    Release Date: July, 4th 2009                                       ///
004:  * ///                    PLASMA is a software package provided by Univ. of Tennessee,       ///
005:  * ///                    Univ. of California Berkeley and Univ. of Colorado Denver          /// */
006: 
007: /* /////////////////////////// P /// U /// R /// P /// O /// S /// E /////////////////////////// */
008: // PLASMA_sposv_Tile - Computes the solution to a system of linear equations A * X = B,
009: // where A is an N-by-N symmetric positive definite (or Hermitian positive definite
010: // in the complex case) matrix and X and B are N-by-NRHS matrices.
011: // The Cholesky decomposition is used to factor A as
012: //
013: //   A = U**T * U, if uplo = PlasmaUpper, or
014: //   A = L * L**T, if uplo =  PlasmaLower,
015: //
016: // where U is an upper triangular matrix and  L is a lower triangular matrix.
017: // The factored form of A is then used to solve the system of equations A * X = B.
018: // All matrices are passed through descriptors. All dimensions are taken from the descriptors.
019: 
020: /* ///////////////////// A /// R /// G /// U /// M /// E /// N /// T /// S ///////////////////// */
021: // uplo     PLASMA_enum (IN)
022: //          Specifies whether the matrix A is upper triangular or lower triangular:
023: //          = PlasmaUpper: Upper triangle of A is stored;
024: //          = PlasmaLower: Lower triangle of A is stored.
025: //
026: // A        float* (INOUT)
027: //          On entry, the symmetric positive definite (or Hermitian) matrix A.
028: //          If uplo = PlasmaUpper, the leading N-by-N upper triangular part of A
029: //          contains the upper triangular part of the matrix A, and the strictly lower triangular
030: //          part of A is not referenced.
031: //          If UPLO = 'L', the leading N-by-N lower triangular part of A contains the lower
032: //          triangular part of the matrix A, and the strictly upper triangular part of A is not
033: //          referenced.
034: //          On exit, if return value = 0, the factor U or L from the Cholesky factorization
035: //          A = U**T*U or A = L*L**T.
036: //
037: // B        float* (INOUT)
038: //          On entry, the N-by-NRHS right hand side matrix B.
039: //          On exit, if return value = 0, the N-by-NRHS solution matrix X.
040: 
041: /* ///////////// R /// E /// T /// U /// R /// N /////// V /// A /// L /// U /// E ///////////// */
042: //          = 0: successful exit
043: //          > 0: if i, the leading minor of order i of A is not positive definite, so the
044: //               factorization could not be completed, and the solution has not been computed.
045: 
046: /* //////////////////////////////////// C /// O /// D /// E //////////////////////////////////// */
047: #include "common.h"
048: 
049: int PLASMA_sposv_Tile(PLASMA_enum uplo, PLASMA_desc *A, PLASMA_desc *B)
050: {
051:     PLASMA_desc descA = *A;
052:     PLASMA_desc descB = *B;
053:     plasma_context_t *plasma;
054: 
055:     plasma = plasma_context_self();
056:     if (plasma == NULL) {
057:         plasma_fatal_error("PLASMA_sposv_Tile", "PLASMA not initialized");
058:         return PLASMA_ERR_NOT_INITIALIZED;
059:     }
060:     /* Check descriptors for correctness */
061:     if (plasma_desc_check(&descA) != PLASMA_SUCCESS) {
062:         plasma_error("PLASMA_sposv_Tile", "invalid first descriptor");
063:         return PLASMA_ERR_ILLEGAL_VALUE;
064:     }
065:     if (plasma_desc_check(&descB) != PLASMA_SUCCESS) {
066:         plasma_error("PLASMA_sposv_Tile", "invalid second descriptor");
067:         return PLASMA_ERR_ILLEGAL_VALUE;
068:     }
069:     /* Check input arguments */
070:     if (uplo != PlasmaUpper && uplo != PlasmaLower) {
071:         plasma_error("PLASMA_sposv_Tile", "illegal value of uplo");
072:         return -1;
073:     }
074:     /* Quick return - currently NOT equivalent to LAPACK's
075:      * LAPACK does not have such check for DPOSV */
076: /*
077:     if (min(N, NRHS) == 0)
078:         return PLASMA_SUCCESS;
079: */
080:     plasma_parallel_call_2(plasma_pspotrf,
081:         PLASMA_enum, uplo,
082:         PLASMA_desc, descA);
083: 
084:     if (PLASMA_INFO == PLASMA_SUCCESS)
085:     {
086:         plasma_parallel_call_7(plasma_pstrsm,
087:             PLASMA_enum, PlasmaLeft,
088:             PLASMA_enum, uplo,
089:             PLASMA_enum, uplo == PlasmaUpper ? PlasmaTrans : PlasmaNoTrans,
090:             PLASMA_enum, PlasmaNonUnit,
091:             float, 1.0,
092:             PLASMA_desc, descA,
093:             PLASMA_desc, descB);
094: 
095:         plasma_parallel_call_7(plasma_pstrsm,
096:             PLASMA_enum, PlasmaLeft,
097:             PLASMA_enum, uplo,
098:             PLASMA_enum, uplo == PlasmaUpper ? PlasmaNoTrans : PlasmaTrans,
099:             PLASMA_enum, PlasmaNonUnit,
100:             float, 1.0,
101:             PLASMA_desc, descA,
102:             PLASMA_desc, descB);
103:     }
104:     return PLASMA_INFO;
105: }