Transform a boost::array into NumericVector in Rcpp

前端 未结 2 1078
清歌不尽
清歌不尽 2021-01-25 20:23

In my C++ script (run in R using Rcpp), I defined :

typedef boost::array< double ,3 > state_type;

Now, I want to create a function to tra

相关标签:
2条回答
  • 2021-01-25 20:44

    How about

    Rcpp::NumericVector boost_array_to_nvec(state_type const& s) {
        Rcpp::NumericVector nvec(s.size());
        for (size_t i = 0; i < s.size(); ++i) {
            nvec[i] = s[i];
        }
        return nvec;
    }
    state_type nvec_to_boost_array(Rcpp::NumericVector const& nvec) {
        state_type s;
        for (size_t i = 0; i < s.size(); ++i) {
            s[i] = nvec[i];
        }
        return s;
    }
    ...
    state_type s {0,0,0};
    Rcpp::NumericVector nvec = boost_array_to_nvec(s);
    s = nvec_to_boost_array(nvec);
    

    If you have to do this a lot of times. This might not be the most efficient way of doing the transformation. But now you have to look that nvec is already allocated to the correct size.

    void boost_array_to_nvec(state_type const& s, Rcpp::NumericVector& nvec) {
        for (size_t i = 0; i < s.size(); ++i) {
            nvec[i] = s[i];
        }
    }
    void nvec_to_boost_array (Rcpp::NumericVector const& nvec, state_type& s) {
        for (size_t i = 0; i < s.size(); ++i) {
            s[i] = nvec[i];
        }
    }
    ...
    state_type s {0,0,0};
    Rcpp::NumericVector nv(3);
    boost_array_to_nvec(s, nv);
    nvec_to_boost_array(nv, s);
    
    0 讨论(0)
  • 2021-01-25 20:50

    If you want to have seamless integration you will have to extend Rcpp::as<T>(obj) and Rcpp::wrap(obj). How to do this is covered in the vignette Extending Rcpp. However, there is also an excellent entry in the Rcpp gallery that already covers a very similar case: Converting to and from boost::numeric::ublas::vector<double>.

    If you are content with only using state_type and not the general template, then you can use something like this:

    #include <RcppCommon.h>
    // [[Rcpp::depends(BH)]]
    #include <boost/array.hpp>
    typedef boost::array< double ,3 > state_type;
    
    namespace Rcpp {
    // non-intrusive extension via template specialisation
    template <> state_type as(SEXP s);
    // non-intrusive extension via template specialisation
    template <> SEXP wrap(const state_type &s);
    }
    
    #include <Rcpp.h>
    
    // define template specialisations for as and wrap
    namespace Rcpp {
    template <> state_type as(SEXP stsexp) {
      Rcpp::NumericVector st(stsexp);
      state_type result;
      if (st.size() != result.size()) Rcpp::stop("Incompatible length!");
      std::copy(st.begin(), st.end(), result.begin());
      return result;
    }
    
    template <> SEXP wrap(const state_type &st) {
      Rcpp::NumericVector result(st.size());
      std::copy(st.begin(), st.end(), result.begin());
      return Rcpp::wrap(result);
    }
    }
    
    // make use of the new possibilities
    // [[Rcpp::export]]
    state_type alterStateType(state_type &st) {
      for (size_t i = 0; i < st.size(); ++i) {
        st[i] = i * st[i];
      }
      return st;
    }
    
    /*** R
    alterStateType(1:3)
    */
    
    0 讨论(0)
提交回复
热议问题