/*--------------------------------------------------------------------------------------
* DSYRK does the operation C = C + A' * A in place
*
* Syntax: dsyrk(C,A) --> does C = C + A' * A (only lower triangle part)
* dsyrk(C) --> fills the upper triangle with the lower triangle
*
* C = a real double full N x N matrix
* A = a real double full K x N matrix
*
* The intent is to first initialize C, then call dsyrk(C,A) in a loop for various A
* matrices, then after the loop call dsyrk(C) once to fill in the upper triangle part.
* The code does the operations on C in place, so it is up to the user to make sure
* that C is not shared with any other variable prior to calling dsyrk.
*
* The code uses ptrdiff_t for the integer types because that is what the header file
* blas.h uses for the dsyrk function arguments.
*
* Programmer: James Tursa
*-------------------------------------------------------------------------------------- */
#include "mex.h"
#include "blas.h"
void xFILLPOS(double *Cpr, ptrdiff_t n);
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double alpha = 1.0, beta = 1.0;
double *Apr, *Cpr;
char uplo = 'L';
char trans = 'T';
ptrdiff_t m, n, k, p, lda, ldc;
if( nlhs ) {
mexErrMsgTxt("Too many outputs ... this routine does all operations in-place");
}
if( nrhs == 2 ) {
Cpr = mxGetPr(prhs[0]);
m = mxGetM(prhs[0]);
n = mxGetN(prhs[0]);
Apr = mxGetPr(prhs[1]);
k = mxGetM(prhs[1]);
p = mxGetN(prhs[1]);
if( m != n || !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]) ||
mxGetNumberOfDimensions(prhs[0]) != 2 ) {
mexErrMsgTxt("1st input must be real double non-sparse square matrix");
}
if( p != n || !mxIsDouble(prhs[1]) || mxIsComplex(prhs[1]) || mxIsSparse(prhs[1]) ||
mxGetNumberOfDimensions(prhs[1]) != 2 ) {
mexErrMsgTxt("2nd input must be real double non-sparse matrix compatible with 1st input");
}
lda = k;
ldc = n;
dsyrk( &uplo, &trans, &n, &k, &alpha, Apr, &lda, &beta, Cpr, &ldc );
} else if( nrhs == 1 ) {
Cpr = mxGetPr(prhs[0]);
m = mxGetM(prhs[0]);
n = mxGetN(prhs[0]);
if( m != n || !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]) ||
mxGetNumberOfDimensions(prhs[0]) != 2 ) {
mexErrMsgTxt("1st input must be real double non-sparse square matrix");
}
xFILLPOS(Cpr,n);
} else {
mexErrMsgTxt("Need exactly 1 or 2 inputs");
}
}
/*--------------------------------------------------------------------------------------
* Fill the upper triangle with contents of the lower triangle
*-------------------------------------------------------------------------------------- */
void xFILLPOS(double *Cpr, ptrdiff_t n)
{
double *source, *target;
register ptrdiff_t i, j;
source = Cpr + 1;
target = Cpr + n;
for( i=1; i<n; i++ ) {
for( j=i; j<n; j++ ) {
*target = *source;
target += n;
source++;
}
source += i + 1;
target = source + n - 1;
}
}
Best Answer