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; }