5

I need to use a Fortran routine called dgebal (documentation here) in my Rcpparmadillo code. I have included the following headers:

# include <RcppArmadillo.h>
# include <math.h>

However, when I try to compile my code using sourceCpp() I get the following error:

error: 'dgebal_' was not declared in this scope

If I further include <R_ext/Lapack.h> and <R_ext/BLAS.h>, the code compiles without error and runs fine. However the compiler throws a bunch of warnings like this:

C:/PROGRA~1/R/R-32~1.3/include/R_ext/BLAS.h:49:64: warning: declaration of 'double dasum_(const int*, const double*, const int*)' with C language linkage [enabled by default]
C:/PROGRA~1/R/R-32~1.3/library/RCPPAR~1/include/armadillo_bits/def_blas.hpp:76:1: warning: conflicts with previous declaration 'double arma::dasum_(arma::blas_int*, const double*, arma::blas_int*)' [enabled by default]

There are many more warnings similar to this. Am I correct to assume this is caused by the LAPACK library shipped with Rcpparmadillo not including dgebal, which is however included with R's LAPACK library? Should I be concerned with these warnings? And finally, is there any way to use dgebal in my Rcpparmadillo code without compilation warnings? Both Rcpp and Rcpparmadillo are up to date. Operating system is Windows 8.1 64bit.

EDIT: Thanks @coatless and @Dirk Eddelbuettel for pointing out that this is not an Rcpparmadillo issue. Nevertheless my problem persists and I would like suggestions on how to get around this. Below is a working example code illustrating my problem. It compiles fine but produces a lot of the aforementioned warnings, which does not seem to affect the intended functionality, at least according to my limited testing. If I remove the two headers R_ext/Lapack.h and R_ext/BLAS.h, the compiler throws the aforementioned error.

#include <RcppArmadillo.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <R.h>
#include <Rinternals.h>
#include <Rmath.h>
#include <R_ext/Lapack.h>
#include <R_ext/BLAS.h>


// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
List R_dgebal2(SEXP x)
{
  SEXP dims, z, Scale, i_1, i_2;
  int n, info;

  dims = Rf_getAttrib(x, R_DimSymbol);
  n = INTEGER(dims)[0];


  z = Rf_duplicate(x); Scale = Rf_allocVector(REALSXP, n);
  i_1 = Rf_allocVector(INTSXP, 1); i_2 = Rf_allocVector(INTSXP, 1);

  F77_CALL(dgebal)("B", &n, REAL(z), &n, INTEGER(i_1), INTEGER(i_2),
           REAL(Scale), &info);

  arma::mat zz = as<arma::mat>(wrap(z));
  arma::vec scale2 = as<arma::vec>(wrap(Scale));
  int i1=as<int>(wrap(i_1)), i2=as<int>(wrap(i_2));
  return List::create(_["z"]=zz, _["scale"]=scale2, _["i1"]=i1, _["i2"]=i2);

}

// Test in R
/*** R
Q <- matrix(c(-1.918206e-01,5.999147e-01,0.000000e+00,0.000000e+00,0.000000e+00,1.106148e-01,
              -1.152574e+00,5.716490e-01,0.000000e+00,0.000000e+00,0.000000e+00,5.526595e-01,
              -1.256864e+00,3.905685e+04,0.000000e+00,0.000000e+00,0.000000e+00,1.929101e-01,
              -3.905721e+04,0.000000e+00,8.120577e-02,0.000000e+00,4.923053e-01,3.572873e-01,0.000000e+00),
              nrow = 5, byrow = T)
R_dgebal2(Q)
*/
aenima
  • 367
  • 1
  • 11
  • 2
    RcppArmadillo uses R's LAPACK installation. Why are you trying to access a fortran routine? – coatless Dec 12 '16 at 05:57
  • 2
    _"LAPACK library shipped with Rcpparmadillo"_ Completely wrong. RcppArmadillo never *ever* ships LAPACK but relies on the LAPACK R knows / was built with which _can_ be a local copy. This has been discussed a million times, see here, at the GH repo (issues) and on the list. If you were to supply a _complete_ example we could test on OS X and Linux. – Dirk Eddelbuettel Dec 12 '16 at 12:35
  • @coatless: Because I need to do matrix balancing, which is not readily available in armadillo. The Fortran routine `dgebal` does this. – aenima Dec 12 '16 at 23:14
  • @DirkEddelbuettel: Thanks for pointing that out. I apologize for my misunderstanding of how LAPACK linking works in Rcpparmadillo. I have added a working example illustrating my problem. – aenima Dec 12 '16 at 23:16
  • I don't anything about `dgebal` in particular, but the _general_ fix to needed some extra is to link against (if a library has it; doesn't seem to be the case with the LAPACK we use here) or to included it yourself in your package. Now, there are some issue having both Fortran and C++ in the same package; see the R documentation. – Dirk Eddelbuettel Dec 12 '16 at 23:26
  • @DirkEddelbuettel: Could you please point me to the link of the R documentation where the specifics are? Thanks. – aenima Dec 13 '16 at 04:02

1 Answers1

11

I have figured this out. I just created a local header file with the following lines and #included it in my .cpp file. Compiles fine with no warnings or errors.

#ifdef ARMA_USE_LAPACK

#if !defined(ARMA_BLAS_CAPITALS)

 #define arma_dgebal dgebal

#else
 #define arma_dgebal DGEBAL

#endif

extern "C"
void arma_fortran(arma_dgebal)(char* job, int* n, double* a, int* lda,
                  int* ilo, int* ihi, double* scale, int* info);

#endif
aenima
  • 367
  • 1
  • 11
  • 5
    Congratulations, you worked out how to call a Fortran routine in Lapack not already accessed by Armadillo using its framework. That is useful to have here, so I just upvoted it. – Dirk Eddelbuettel Dec 15 '16 at 00:08
  • 1
    @DirkEddelbuettel: Thanks for the upvote. I imagine this is probably not a very commonly seen issue but it'll be nice to have an simple and generalizable solution in case others need it too. – aenima Dec 15 '16 at 04:45