[Rcpp-devel] Casting error from checking package on CRAN under C++14, g++

Dirk Eddelbuettel edd at debian.org
Sun Jan 24 16:33:54 CET 2016


Terrance,

On 21 January 2016 at 21:46, Dirk Eddelbuettel wrote:
| 
| Hi Terrance,
| 
| On 21 January 2016 at 16:44, terrance savitsky wrote:
| | Hi Rcpp experts, The CRAN maintainers inform me that when testing one of my
| | packages under 
| | 
| | g++ -std=gnu++14 (logs with gcc 5.3)
| | 
| | that the following code snippet,
| | 
| | IntegerVector dpr = diff(pr); /* pr is an Rcpp::IntegerVector */
| | icolvec diffpersons(dpr.begin(), nc - 1, false);
| | 
| | generates the following error:
| | 
| | error: no matching function for call to ‘arma::Col<long long int>::Col(Rcpp::Vector<13>::iterator, int, bool)’
| |      icolvec diffpersons(dpr.begin(), nc - 1, false);
| | 
| | where I'm writing (the memory for) an Rcpp:: IntegerVector to an arma::icolvec. The default width for an Armadillo signed integer under C++11 and C++14 is 64-bit (long long).  I'd appreciate your insight on whether there is an alternate approach to casting an arma::icolvec from an Rcpp::IntegerVector that can deal with a 64-bit integer; for example, will as<icolvec>() work?
| 
| As you probably noticed, you were not the only one receiving this email.
| 
| To give you some background, the author of that very email insisted for many
| years that the only actual C++ standard that mattered for R was C++98 (and
| yes, it is referenced in the email) meaning that the interim C++03 changes
| 'never existed'.  This meant in particular that 'long long' was not
| allowed. We have numerous #ifdef's around it because of that. Huge pain.
| 
| And so did Armadillo which you use.  Now if you check the Armadillo docs (as
| I just had to as I had a very similar issue an older package of mine in the
| same email), I saw in Conrad's docs (at http://arma.sourceforge.net/docs.html#Col)
| 
|   uword, sword
|   uword is a typedef for an unsigned integer type; it is used for matrix
|   indices as well as all internal counters and loops 
| 
|   sword is a typedef for a signed integer type
| 
|   The minimum width of both uword and sword is either 32 or 64 bits:
|     when using the old C++98 / C++03 standards, the default width is 32 bits
|     when using the new C++11 / C++14 standards, the default width is 64 bits on
|        64-bit platforms (as of Armadillo 5.000) 
| 
| and that is key. Conrad now uses 64 bit (== long long) when C++11 or C++14 is
| used.  So where you used to use the 'icolvec' before, you may now need
| Col<int32_t> -- or else you will get a 'long long' when R wants an
| 'int'. Won't fly.
| 
| I just made that change in three spots in the package in question, and the
| very error reported against my package goes away.  I started from a basic
| Docker container providing on debian:unstable -- which I knew had g++-5.3 as
| in the report we got -- and install R, Rcpp and RcppArmadillo after which
| this was easy to test.
| 
| To be explicit, my diff was
| 
| diff --git a/src/devol.cpp b/src/devol.cpp
| index 7b1ea80..ca4d063 100644
| --- a/src/devol.cpp
| +++ b/src/devol.cpp
| @@ -32,13 +32,13 @@ void devol(double VTR, double f_weight, double f_cross, int i_bs_flag,
|      }
|      const int urn_depth = 5;                    // 4 + one index to avoid 
|      Rcpp::NumericVector par(i_D);               // initialize parameter vector to pass to evaluate function 
| -    arma::icolvec::fixed<urn_depth> ia_urn2;    // fixed-size vector for urn draws
| -    arma::icolvec ia_urntmp(i_NP);              // so that we don't need to re-allocated each time in permute
| +    arma::Col<int32_t>::fixed<urn_depth> ia_urn2;    // fixed-size vector for urn draws
| +    arma::Col<int32_t> ia_urntmp(i_NP);              // so that we don't need to re-allocated each time in permute
|      arma::mat initialpop(i_D, i_NP); 
|      int i_nstorepop = static_cast<int>(ceil(static_cast<double>((i_itermax - i_storepopfrom) / i_storepopfreq)));
|      int p_NP = round(i_pPct * i_NP);            // choose at least two best solutions 
|      p_NP = p_NP < 2 ? 2 : p_NP;
| -    arma::icolvec sortIndex(i_NP);              // sorted values of ta_oldC 
| +    arma::Col<int32_t> sortIndex(i_NP);         // sorted values of ta_oldC 
|      if (i_strategy == 6) {
|          for (int i = 0; i < i_NP; i++) 
|              sortIndex[i] = i; 
| edd at max:~/git/rcppde(feature/c++14)$ 

A simpler fix might be to use this construct from the Armadillo header:

  #if defined(ARMA_32BIT_WORD)
    #undef ARMA_64BIT_WORD
  #endif

I think that if you define ARMA_32BIT_WORD, but conditional on being in
C++11/C++14 contexts, then the Armadillo should continue to use 32-bit
integers which you can pass to R as before.  That may be worth testing.

Hope this helps,  Dirk
 
| Hope this helps.
| 
| Dirk
| 
| -- 
| http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
-- 
http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list