• R-package including the C++ library EIGEN without assistence of Rcpp.

This file records notes calling Eigen of C/C++ from R, in which the C/C++ functions call the third C/C++ library Eigen. The library Eigen is one of the most inportant library of C/C++ for linear algebra: matrices, vectors, numerical solvers, and related algorithms. More details can be found at the official website.

1 Example for eigentest

2 The directory tree

  • one may create the files by
package.skeleton(name = "eigentest",
                 code_files=c("generateMatrix.R"),
                 cpp_files="cfunct.cpp",
                 example_code = TRUE)
  • First of all, we create some files and subdirectories. The directory tree looks like the follows.
.
├── README.md
├── NAMESPACE
├── DESCRIPTION
├── inst
├   ├── eigentest-manual.pdf
├   └── include
├       └── Eigen
├── man
├   ├── eigentest-package.Rd
├   └── generateMatrix.Rd
├── R
├   └── generateMatrix.R
└── src
    ├── cfunct.c
    ├── Makevars
    └── Makevars.win

3 The folder “src”

  • Prepare the C++ codes
  • The function below returns a matrix that is a matrix in C++, and stores the given numbers. Here, we save this function in a Cpp file named cfunct.cpp.
//#include "cfunct.h"
#include <stdio.h>  
#include <stdlib.h> 
#include <string.h>
#include <Eigen/Eigen>
#include <Eigen/Dense>
#include <iostream>
#include <R.h>
#include <Rinternals.h> 
#include <R_ext/Rdynload.h>

using namespace Eigen;

extern "C"{
Eigen::MatrixXd _MatrixPlus_(Eigen::MatrixXd Data, int d)
{
  Eigen::MatrixXd M = Eigen::MatrixXd::Constant(d,d,2);  
  M = (M + Data)*50; 
  return M;
}


SEXP ExportsMatrixPlus(SEXP d0){
    int i,j,*d_ = INTEGER(d0);
    Eigen::MatrixXd M_, M1_;    
    int d = d_[0];  
    double *M;
    SEXP rM, list, list_names;
    M1_ = Eigen::MatrixXd::Identity(d, d);      
    M_ = _MatrixPlus_(M1_,d);
    // Outcome
    PROTECT(rM = allocVector(REALSXP, d*d));
    M = REAL(rM);
    for(i=0;i<d;i++) for(j=0;j<d;j++)   M[i*d+j] = M_(i,j);
    
    char *names[2] = {"M","d"};
    PROTECT(list_names = allocVector(STRSXP, 1));
    SET_STRING_ELT(list_names, 0,  mkChar(names[0]));
    PROTECT(list = allocVector(VECSXP, 1)); 
    SET_VECTOR_ELT(list, 0, rM);
    setAttrib(list, R_NamesSymbol, list_names); 
    
    UNPROTECT(3); 
    return list;    
}


static const R_CallMethodDef CallEntries[] = {
    {"ExportsMatrixPlus", (DL_FUNC) &ExportsMatrixPlus, 1},
    {NULL, NULL, 0}
};

void R_init_eigentest(DllInfo *dll) {
    R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
    R_useDynamicSymbols(dll, FALSE);
}

}
  • Makevars
PKG_CPPFLAGS = -I../inst/include
PKG_CXXFLAGS = -DEIGEN_DONT_PARALLELIZE $(SHLIB_OPENMP_CXXFLAGS)
  • Makevars.win
PKG_CPPFLAGS = -I../inst/include -I.
PKG_CXXFLAGS = -DEIGEN_DONT_PARALLELIZE $(SHLIB_OPENMP_CXXFLAGS)

4 The folder “R”

  • write an R screpts to call Cpp funuctions
generateMatrix <- function(n){
  if(n<=0){
    stop("n must be a positive integer!")
    return(0)    
  }
  else{
    result = .Call("ExportsMatrixPlus", as.integer(n), PACKAGE = "eigentest")
    #result = .Call("ExportsMatrixPlus",as.integer(n))
    M = matrix(result$M,n,n)
    return(M)
  }
}

5 The folder “man”

  • eigentest-package.Rd
  • generateMatrix.Rd

6 The folder “inst”

  • The manual, eigentest-manual.pdf
  • include
    • Eigen

7 DESCRIPTION

Package: eigentest
Type: Package
Title: eigentest
Version: 0.1.0
Authors@R: c(person(given = "Xu", family = "Liu", role = c("aut","cre"), email = "liu.xu@sufe.edu.cn")
            )
Author: Xu Liu [aut,cre]
Maintainer: Xu Liu <liu.xu@sufe.edu.cn>
Description: R package including the C++ library "EIGEN".
License: GPL (>= 2)
RoxygenNote: 6.0.1
NeedsCompilation: yes
Repository: github
URL: https://github.com/xliusufe/eigentest
Encoding: UTF-8
Packaged: 2020-05-20 01:35:21 UTC; admin

8 NAMESPACE

useDynLib(eigentest, .registration=TRUE)
exportPattern("^[[:alpha:]]+")
export(generateMatrix)

9 Compile pkgs

  • Check the package on CMD (Win OS) or terminal (MacOS/Linux OS)
R CMD check eigentest
  • or on R console
system("R CMD check eigentest")
  • build pacakge
R CMD INSTALL --build eigentest
  • A .bat file is a good way to check or build pakcages
R CMD check eigentest

PAUSE
  • Other useful command. on cmd (Win OS) or terminal (MacOS/Linux)
    R CMD Rd2pdf myrpk