Esempio n. 1
0
void blocked_cholesky( int NB, float A[NB][NB] ) {
  int i, j, k;

  for (k=0; k<NB; k++) {
#pragma omp task depend(inout:A[k][k])
    spotrf (A[k][k]) ;
    for (i=k+1; i<NT; i++)
#pragma omp task depend(in:A[k][k]) depend(inout:A[k][i])
      strsm (A[k][k], A[k][i]);
    // update trailing submatrix
    for (i=k+1; i<NT; i++) {
      for (j=k+1; j<i; j++)
#pragma omp task depend(in:A[k][i],A[k][j]) depend(inout:A[j][i])
          sgemm( A[k][i], A[k][j], A[j][i]);
#pragma omp task depend(in:A[k][i]) depend(inout:A[i][i])
      ssyrk (A[k][i], A[i][i]);
    }
  }
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    
    mwIndex i, j; /* indeces for populating lower triangle when finished. */
    mwSize n;   /* Size of the matrix. */
    mwSignedIndex info;     /* flag for success in dpotrf, spotrf, dpotri, spotri */
    char *uplo = "U";     /* upper or lower triangle */
    mxClassID type;       /* array type */
    
    /* If we don't pass in the correct number of arguments, throw error. */
    if (nrhs!=1) {
        mexErrMsgIdAndTxt("mexFunction:invChol_mex:numInputs",
                "1 input required: A (square matrix)");
    }
    
    type = mxGetClassID(prhs[0]); /* get the array type */
    
    n = mxGetM(prhs[0]); /* input matrix dimension */
    /* check for symmetric matrix*/
    if (n!=mxGetN(prhs[0])) {
        mexErrMsgIdAndTxt("MATLAB:invChol_mex:matchdims",
                "matrix is not symmetric");
    }
    /* create output matrix (fortran modifies the input so we need to copy the input to output) */
    plhs[0]=mxDuplicateArray(prhs[0]);
    
    /* If we passed in an empty return an empty. */
    if (n==0) {
        return;
    }
    
    /* double precision */
    if(type==mxDOUBLE_CLASS)
    {
        double *B; /* double pointer to input & output matrices*/
        B = mxGetPr(plhs[0]); /* output matrix pointer */
        
        dpotrf( uplo, &n, B, &n, &info ); /* Double Cholesky decomposition */
        
        /* check for success */
        if (info<0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:dpotrf:illegalvalue",
                    "cholesky decomposition failed: illegal value ");
        }
        if (info>0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:dpotrf:notposdef",
                    "cholesky decomposition failed: matrix is not positive definite");
        }
        
        dpotri( uplo, &n, B, &n, &info ); /* Double Inverse using Cholesky decomposition */
        
        /* check for success */
        if (info<0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:dpotri:illegalvalue",
                    "failed to invert: illegal value");
        }
        
        if (info>0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:dpotri:singularmatrix",
                    "failed to invert: a diagonal element was 0");
        }
        
        /* populate the lower triangle */
        for (i=0; i<n; i++) {
            for (j=i+1; j<n; j++) {
                B[n*i+j]=B[j*n+i];
            }
        }
        
    } else if (type==mxSINGLE_CLASS) {
        float *B; /* float pointer to input and output matrices */
        B = (float*) mxGetData(plhs[0]); /* output matrix pointer */
        
        spotrf( uplo, &n, B, &n, &info ); /* Double Cholesky decomposition */
        
        /* check for success */
        if (info<0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:spotrf:illegalvalue",
                    "cholesky decomposition failed: illegal value ");
        }
        if (info>0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:spotrf:notposdef",
                    "cholesky decomposition failed: matrix is not positive definite");
        }
        
        spotri( uplo, &n, B, &n, &info ); /* Double Inverse using Cholesky decomposition */
        
        /* check for success */
        if (info<0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:spotri:illegalvalue",
                    "failed to invert: illegal value");
        }
        
        if (info>0) {
            mexErrMsgIdAndTxt("MATLAB:invChol_mex:spotri:singularmatrix",
                    "failed to invert: a diagonal element was 0");
        }
        
        /* populate the lower triangle*/
        for (i=0; i<n; ++i)
        {
            for (j=i+1; j<n; ++j)
            {
                B[n*i+j]=B[j*n+i];
            }
        }
        
    } else {
        mexErrMsgIdAndTxt("MATLAB:invChol_mex:illegaltype",
                "only single or double matrix inputs are allowed");
    }
    return;
}