How to determine the class of object stored in SEXP in Rcpp? [duplicate]

喜夏-厌秋 提交于 2019-12-22 00:39:46

问题


//[[Rcpp::export]]
int Class_data(SEXP data) {
    /*
       return 0 if class of data is matrix
       else return -1 
    */
}

How to determine the class of data in the above case? If data belongs to matrix class return 0 else return -1.


回答1:


Depending on what type of object you are checking for, there may be a predefined Rf_isWhatever macro, or you may need to use the Rf_inherits(object, "Whatever") macro, both defined in the R source code, and available through the Rcpp header. For example,

#include <Rcpp.h>

// [[Rcpp::export]]
int is_matrix(SEXP data) {
    return Rf_isMatrix(data) ? 0 : -1;
}

// [[Rcpp::export]]
int is_data_frame(SEXP x) {
    return Rf_inherits(x, "data.frame") ? 0 : -1;
}

/*** R

is_matrix(matrix(1:6, 2))
#[1] 0

is_matrix(data.frame(1:5))
#[1] -1

is_data_frame(data.frame(1:5))
#[1] 0

is_data_frame(matrix(1:6, 2))
#[1] -1

*/

For reference, you can check the source code to see what is available.




回答2:


Normally, you would know in advance what type the object is when working with Rcpp as you would specify:

//[[Rcpp::export]]
int Class_data(Rcpp::NumericMatrix) {
  // code to reduce return to int
  return 1;
}

Of course, there are exceptions when working with different element types (e.g. logical vs. character vs. numeric) and having one call function. I've included an example of this at the end.

Though, in the case when you do not, the best to do is use isMatrix in R's vocab:

INLINE_FUN Rboolean isMatrix(SEXP s)
{
    SEXP t;
    if (isVector(s)) {
    t = getAttrib(s, R_DimSymbol);
    /* You are not supposed to be able to assign a non-integer dim,
       although this might be possible by misuse of ATTRIB. */
    if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)
        return TRUE;
    }
    return FALSE;
}

Implementation

To handle a larger amount of objects (logical, character, etc..), you want an internal switch given in R's do_is() function.

That may be a bit too big though and you may want help in dispatching different object types. To do so, see this example:

#include <Rcpp.h>

// Create a template generic (look up C++ templates)
template <int RTYPE>
int count_me(Vector<RTYPE> v){
    return v.size() ; // Just want to show it can return sizes of different array types
}

// [[Rcpp::export]]
int fake_switch(SEXP x){

    // customize with different functions
    // Or, just pass different types into the template.
    switch( TYPEOF(x) ){
    case INTSXP: return count_me<INTSXP>(x); // integers
    case REALSXP: return count_me<REALSXP>(x); // numeric
    case STRSXP: return count_me<STRSXP>(x); // strings
    default: Rcpp::stop("type not handled"); // no support for obj
    }
    return -1; // should never be trigger but here to make the compiler happy
}


来源:https://stackoverflow.com/questions/37665361/how-to-determine-the-class-of-object-stored-in-sexp-in-rcpp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!