[Rd] speedup for as.matrix.dist

Romain Francois romain.francois at dbmail.com
Sat Apr 18 15:35:41 CEST 2009


Hello,

I am trying to patch as.matrix.dist to achieve some speedup.

 > m <- expand.grid( x = 1:20, y = 1:20, z = 1:20 )
 > d <- dist( m )
 > system.time( out <- stats:::as.matrix.dist( d ) )
   user  system elapsed
 15.355   3.110  19.123
 > system.time( out <- as.matrix.dist( d ) )
   user  system elapsed
  3.153   0.480   3.782

The code below works if I deploy it in an additional package, but not 
when I patch the "stats" package, I get that kind of message:
  C symbol name "as_matrix_dist" not in load table

Romain


as.matrix.dist <- function(x, ...) {
    size <- as.integer(attr(x, "Size"))
    if( !is.numeric(x) ){
        storage.mode(x) <- "numeric"
    }
    df <- .External( "as_matrix_dist",
        x = x, size = size, PACKAGE = "stats" )
    labels <- attr(x, "Labels")
    dimnames(df) <- if(is.null(labels)) list(1L:size,1L:size) else 
list(labels,labels)
    df
}



/**
 * as.matrix.dist( d )
 */
SEXP as_matrix_dist(SEXP args){
   
    args = CDR( args ) ; SEXP x = CAR( args );
    args = CDR( args ) ; SEXP size = CAR( args );
   
    int i,j,k;
    int s = INTEGER(size)[0];
    SEXP d ;
    PROTECT( d = allocVector( REALSXP, s*s) );
    double element;
    for( i=0,k=0; i<s; i++){
        REAL(d)[i+s*i] = 0.0 ;
        for( j=i+1; j<s; j++,k++){
            element = REAL(x)[k] ;
            REAL( d )[ i + s*j ] = element ;
            REAL( d )[ j + s*i ] = element ;
        }
    }
    SEXP dims ;
    PROTECT( dims = allocVector(INTSXP, 2 ) );
    INTEGER(dims)[0] = s ;
    INTEGER(dims)[1] = s ;
    setAttrib( d, mkString("dim"), dims );
    UNPROTECT(2); /* d, dims */
    return( d ) ;
}



-- 
Romain Francois
Independent R Consultant
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr



More information about the R-devel mailing list