Skip to content
Prev 39273 / 63424 Next

Problem using F77_CALL(dgemm) in a package

Jason,

FWIW the direct interface (.Call) is more efficient and makes passing things from R simpler:

C_matrix_multiply = function(A,B) .Call("R_matrix_multiply", A, B)

The drawback is a bit more legwork on the C side, but it also gives you more flexibility:

SEXP R_matrix_multiply(SEXP A, SEXP B) {
 	double one = 1.0;
	double zero = 0.0;
	int *dimA = INTEGER(getAttrib(A, R_DimSymbol));
	int *dimB = INTEGER(getAttrib(B, R_DimSymbol));
	SEXP sDimC = PROTECT(allocVector(INTSXP, 2));
	int *dimC = INTEGER(sDimC);
	SEXP C = PROTECT(allocVector(REALSXP, dimA[0] * dimB[1]));
	if (dimA[1] != dimB[0]) error("incompatible matrices!");
	dimC[0] = dimA[0];
	dimC[1] = dimB[1];
	setAttrib(C, R_DimSymbol, sDimC);
	A = PROTECT(coerceVector(A, REALSXP));
	B = PROTECT(coerceVector(B, REALSXP));
	F77_CALL(dgemm)("N","N",dimA,dimB+1,dimA+1,&one,REAL(A),dimA,REAL(B),dimA+1,&zero,REAL(C),dimA);
	UNPROTECT(4);
	return C;
}

For comparison:
.Call:
user  system elapsed 
  0.656   0.008   0.686 

.C:
user  system elapsed 
  0.886   0.044   0.943 


in fact .Call is even a tiny bit faster than %*%:
user  system elapsed 
  0.658   0.004   0.665 

(it's not just a measurement error - it's consistent for more replications etc. - but it's really negligible - possibly just due to dispatch of %*%)

Cheers,
Simon
On Feb 20, 2011, at 5:23 PM, Jason Rudy wrote: