将 Rcpp 数值向量转换为 boost:ublas:vector
Convert Rcpp Numeric Vector into boost:ublas:vector
我正在尝试将 rtype
对象从 boost
转换为 ublas
。
使用我从 Rcpp dev list regarding ublas 中找到的一些代码,我能够 return 将 ublas
向量包装为 rtype
。
例如
// Converts from ublas to rtype
template <typename T>
Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >
ublas2rcpp( const boost::numeric::ublas::vector<T>& x ){
return Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >(
x.begin(), x.end()
) ;
}
为了模仿行为导入行为,我目前在相应长度的 ublas
向量上使用循环,并将 rtype
中的所有内容分配给它。
从循环切换会提高性能吗?
// My attempt to convert from rtype to ublas
// so R can find the libraries
//[[Rcpp::depends(BH)]]
//[[Rcpp::plugins("cpp11")]]
#include <Rcpp.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <boost/numeric/odeint.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
using namespace std;
using namespace Rcpp;
using namespace boost::numeric::ublas;
typedef boost::numeric::ublas::vector< double > vector_type;
typedef boost::numeric::ublas::matrix< double > matrix_type;
template <typename T> /// this need to be fixed up, hopefully working for now though
Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >
ublas2rcpp( const boost::numeric::ublas::vector<T>& x ){
return Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >(
x.begin(), x.end()
) ;
}
// [[Rcpp::export]]
NumericVector main(NumericVector x1)
{
int L =x1.length();
vector_type x(L , 0 ); // initialize the vector to all zero
for(int i=0;i<L;i++)
{
x(i) = x1(i);
}
return(ublas2rcpp(x));
}
首先,抱歉耽搁了。希望我所做的能弥补它。
话虽如此,让我们开始吧!
简介
正在尝试解决两个问题:
- 从 R 转换为 C++ (
Rcpp::as<T>(obj)
)
- 从 C++ 转换为 R (
Rcpp::wrap(obj)
)
幸运的是,有一个名为 Extending Rcpp 的精彩 Rcpp 小插图可以解决自定义 object 问题。遗憾的是,与其他文档相比,小插图的清晰度还有很多不足之处。 (我可能会尝试做一个 PR 来改进它。)
所以,我将尝试通过一些评论来引导您完成这些步骤。请注意,所使用的方法是通过 模板和部分专业化 并且最终会产生一些不错的自动魔法。
解释
第 1 阶段 - 转发声明
在第一阶段,我们必须在参与之前声明我们希望使用的功能的意图 Rcpp.h
。为此,我们将加载一个不同的 header 文件并向 Rcpp::traits
命名空间添加一些定义。
原则上,当我们开始写入文件时,我们必须加载的第一个 header 是 RcppCommon.h
而 而不是 通常的 Rcpp.h
!!如果我们不在 Rcpp.h
调用之前放置前向声明,我们将无法正确注册我们的扩展。
然后,我们必须为 sourceCpp()
添加不同的插件标记,以便在代码编译期间设置适当的标志。在插件之后,我们将包括我们想要使用的实际提升 headers。最后,我们必须在 Rcpp::traits
命名空间中添加两个特殊的 Rcpp 函数声明,Rcpp::as<T>(obj)
和 Rcpp::wrap(obj)
。要启用多种类型,我们必须创建一个 Exporter
class 而不是更直接地调用 template <> ClassName as( SEXP )
。
#include <RcppCommon.h>
// Flags for C++ compiler
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins("cpp11")]]
// Third party library includes that provide the template class of ublas
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix.hpp>
// Provide Forward Declarations
namespace Rcpp {
namespace traits{
// Setup non-intrusive extension via template specialization for
// 'ublas' class boost::numeric::ublas
// Support for wrap
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj);
// Support for as<T>
template <typename T> class Exporter< boost::numeric::ublas::vector<T> >;
}
}
第 2 阶段 - 包括 Rcpp.h
有一个阶段只是为了声明导入顺序可能看起来很无聊,但是如果在前向声明之前包含 Rcpp.h
那么 Rcpp::traits
就不会更新,我们将进入深渊。
因此:
// >> Place <Rcpp.h> AFTER the forward declaration!!!! <<
#include <Rcpp.h>
// >> Place Definitions of Forward Declarations AFTER <Rcpp.h>!!!! <<
第 3 阶段 - 实施扩展
现在,我们必须实际执行前向声明。特别是,唯一会有点问题的实现是 as<>
,因为 wrap()
是直截了当的。
wrap()
要实现 wrap()
,我们必须在 Rcpp 中调用一个名为 Rcpp::traits::r_sexptype_traits<T>::rtype
的内置类型转换索引。由此,我们可以得到一个包含RTYPE
的int
,然后构造一个Rcpp::Vector
。对于矩阵的构造,同样的道理。
as()
对于as<>()
,我们需要考虑传入的模板。此外,我们在Exporter
class定义的正下方设置了一个typedef
,以方便定义要在 get()
方法中使用的 OUT
object。除此之外,我们使用相同的技巧在 C++ T
类型和 R
类型之间来回移动。
为了完成 as<>
,或者从 R 到 C++ 的直接端口,我不得不做一些肮脏的事情:我复制了向量内容。管理此输出的代码在 Exporter
class 的 get()
中给出。您可能希望花一些时间研究使用指针更改分配。我不是很精通 ublas
所以我没有看到解决指针传递的简单方法。
// Define template specializations for as<> and wrap
namespace Rcpp {
namespace traits{
// Defined wrap case
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj){
const int RTYPE = Rcpp::traits::r_sexptype_traits<T>::rtype ;
return Rcpp::Vector< RTYPE >(obj.begin(), obj.end());
};
// Defined as< > case
template<typename T>
class Exporter< boost::numeric::ublas::vector<T> > {
typedef typename boost::numeric::ublas::vector<T> OUT ;
// Convert the type to a valid rtype.
const static int RTYPE = Rcpp::traits::r_sexptype_traits< T >::rtype ;
Rcpp::Vector<RTYPE> vec;
public:
Exporter(SEXP x) : vec(x) {
if (TYPEOF(x) != RTYPE)
throw std::invalid_argument("Wrong R type for mapped 1D array");
}
OUT get() {
// Need to figure out a way to perhaps do a pointer pass?
OUT x(vec.size());
std::copy(vec.begin(), vec.end(), x.begin()); // have to copy data
return x;
}
} ;
}
}
第 4 阶段 - 测试
好吧,让我们看看我们所做的工作是否得到了回报(剧透它做到了!剧透)。要检查,我们应该查看两个不同的区域:
- 函数内的跟踪诊断;
- 自动测试。
两者都在下面给出。请注意,我选择将 ublas
设置缩短为:
// Here we define a shortcut to the boost ublas class to enable multiple ublas types via a template.
// ublas::vector<T> => ublas::vector<double>, ... , ublas::vector<int>
namespace ublas = ::boost::numeric::ublas;
跟踪诊断
// [[Rcpp::export]]
void containment_test(Rcpp::NumericVector x1) {
Rcpp::Rcout << "Converting from Rcpp::NumericVector to ublas::vector<double>" << std::endl;
ublas::vector<double> x = Rcpp::as< ublas::vector<double> >(x1); // initialize the vector to all zero
Rcpp::Rcout << "Running output test with ublas::vector<double>" << std::endl;
for (unsigned i = 0; i < x.size (); ++ i)
Rcpp::Rcout << x(i) << std::endl;
Rcpp::Rcout << "Converting from ublas::vector<double> to Rcpp::NumericVector" << std::endl;
Rcpp::NumericVector test = Rcpp::wrap(x);
Rcpp::Rcout << "Running output test with Rcpp::NumericVector" << std::endl;
for (unsigned i = 0; i < test.size (); ++ i)
Rcpp::Rcout << test(i) << std::endl;
}
测试调用:
containment_test(c(1,2,3,4))
结果:
Converting from Rcpp::NumericVector to ublas::vector<double>
Running output test with ublas::vector<double>
1
2
3
4
Converting from ublas::vector<double> to Rcpp::NumericVector
Running output test with Rcpp::NumericVector
1
2
3
4
此测试按预期执行。进入下一个测试!
自动测试
// [[Rcpp::export]]
ublas::vector<double> automagic_ublas_rcpp(ublas::vector<double> x1) {
return x1;
}
测试调用:
automagic_ublas_rcpp(c(1,2,3.2,1.2))
结果:
[1] 1.0 2.0 3.2 1.2
成功!
第 5 阶段 - Cntrl + C 和 Cntrl + V
这里是阶段给出的上述代码块的组合。如果您将其复制并粘贴到您的 .cpp
文件中,那么一切 都应该 有效。如果没有,请告诉我。
// -------------- Stage 1: Forward Declarations with `RcppCommon.h`
#include <RcppCommon.h>
// Flags for C++ compiler
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins("cpp11")]]
// Third party library includes that provide the template class of ublas
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix.hpp>
// Here we use ublas_vec to enable multiple ublas types via a template.
// ublas::vector<T> => ublas::vector<double>, ... , ublas::vector<int>
namespace ublas = ::boost::numeric::ublas;
// Provide Forward Declarations
namespace Rcpp {
namespace traits{
// Setup non-intrusive extension via template specialization for
// 'ublas' class boost::numeric::ublas
// Support for wrap
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj);
// Support for as<T>
template <typename T> class Exporter< boost::numeric::ublas::vector<T> >;
}
}
// -------------- Stage 2: Including Rcpp.h
// >> Place <Rcpp.h> AFTER the forward declaration!!!! <<
#include <Rcpp.h>
// >> Place Definitions of Forward Declarations AFTER <Rcpp.h>!!!! <<
// -------------- Stage 3: Implementation of Declarations
// Define template specializations for as<> and wrap
namespace Rcpp {
namespace traits{
// Defined wrap case
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj){
const int RTYPE = Rcpp::traits::r_sexptype_traits<T>::rtype ;
return Rcpp::Vector< RTYPE >(obj.begin(), obj.end());
};
// Defined as< > case
template<typename T>
class Exporter< boost::numeric::ublas::vector<T> > {
typedef typename boost::numeric::ublas::vector<T> OUT ;
// Convert the type to a valid rtype.
const static int RTYPE = ::Rcpp::traits::r_sexptype_traits< T >::rtype ;
Rcpp::Vector<RTYPE> vec;
public:
Exporter(SEXP x) : vec(x) {
if (TYPEOF(x) != RTYPE)
throw std::invalid_argument("Wrong R type for mapped 1D array");
}
OUT get() {
// Need to figure out a way to perhaps do a pointer pass?
OUT x(vec.size());
std::copy(vec.begin(), vec.end(), x.begin()); // have to copy data
return x;
}
} ;
}
}
// -------------- Stage 4: Tests
// [[Rcpp::export]]
ublas::vector<double> automagic_ublas_rcpp(ublas::vector<double> x1) {
return x1;
}
// [[Rcpp::export]]
void containment_test(Rcpp::NumericVector x1) {
Rcpp::Rcout << "Converting from Rcpp::NumericVector to ublas::vector<double>" << std::endl;
ublas::vector<double> x = Rcpp::as< ublas::vector<double> >(x1); // initialize the vector to all zero
Rcpp::Rcout << "Running output test with ublas::vector<double>" << std::endl;
for (unsigned i = 0; i < x.size (); ++ i)
Rcpp::Rcout << x(i) << std::endl;
Rcpp::Rcout << "Converting from ublas::vector<double> to Rcpp::NumericVector" << std::endl;
Rcpp::NumericVector test = Rcpp::wrap(x);
Rcpp::Rcout << "Running output test with Rcpp::NumericVector" << std::endl;
for (unsigned i = 0; i < test.size (); ++ i)
Rcpp::Rcout << test(i) << std::endl;
}
结束语
哇...那太多了。希望以上内容提供了足够的理由,因为我相信您可能希望将 1D
向量扩展到 ublas::matrix
等等。此外,等待应该是值得的,因为您现在拥有 Rcpp
的自动转换魔法,因此无需在 return()
语句中调用 ublas2rcpp()
。事实上,您可以将函数的 return 类型简化为 ublas::vector<double>
!
在其他新闻中,我认为可能是什么阻止了您的创作上面的备用模板函数(例如 rcpp2ublas
)无法推断出 Rcpp::Vector
是什么 C++ T
类型。就我个人而言,在 Rcpp GitHub Repo 中仔细研究之后,我不确定是否存在这样的转换索引,或者由于 Shield
的用法,是否应该使用它。深入挖掘转化是另一天的冒险。
我正在尝试将 rtype
对象从 boost
转换为 ublas
。
使用我从 Rcpp dev list regarding ublas 中找到的一些代码,我能够 return 将 ublas
向量包装为 rtype
。
例如
// Converts from ublas to rtype
template <typename T>
Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >
ublas2rcpp( const boost::numeric::ublas::vector<T>& x ){
return Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >(
x.begin(), x.end()
) ;
}
为了模仿行为导入行为,我目前在相应长度的 ublas
向量上使用循环,并将 rtype
中的所有内容分配给它。
从循环切换会提高性能吗?
// My attempt to convert from rtype to ublas
// so R can find the libraries
//[[Rcpp::depends(BH)]]
//[[Rcpp::plugins("cpp11")]]
#include <Rcpp.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <boost/numeric/odeint.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
using namespace std;
using namespace Rcpp;
using namespace boost::numeric::ublas;
typedef boost::numeric::ublas::vector< double > vector_type;
typedef boost::numeric::ublas::matrix< double > matrix_type;
template <typename T> /// this need to be fixed up, hopefully working for now though
Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >
ublas2rcpp( const boost::numeric::ublas::vector<T>& x ){
return Rcpp::Vector< Rcpp::traits::r_sexptype_traits<T>::rtype >(
x.begin(), x.end()
) ;
}
// [[Rcpp::export]]
NumericVector main(NumericVector x1)
{
int L =x1.length();
vector_type x(L , 0 ); // initialize the vector to all zero
for(int i=0;i<L;i++)
{
x(i) = x1(i);
}
return(ublas2rcpp(x));
}
首先,抱歉耽搁了。希望我所做的能弥补它。
话虽如此,让我们开始吧!
简介
正在尝试解决两个问题:
- 从 R 转换为 C++ (
Rcpp::as<T>(obj)
) - 从 C++ 转换为 R (
Rcpp::wrap(obj)
)
幸运的是,有一个名为 Extending Rcpp 的精彩 Rcpp 小插图可以解决自定义 object 问题。遗憾的是,与其他文档相比,小插图的清晰度还有很多不足之处。 (我可能会尝试做一个 PR 来改进它。)
所以,我将尝试通过一些评论来引导您完成这些步骤。请注意,所使用的方法是通过 模板和部分专业化 并且最终会产生一些不错的自动魔法。
解释
第 1 阶段 - 转发声明
在第一阶段,我们必须在参与之前声明我们希望使用的功能的意图 Rcpp.h
。为此,我们将加载一个不同的 header 文件并向 Rcpp::traits
命名空间添加一些定义。
原则上,当我们开始写入文件时,我们必须加载的第一个 header 是 RcppCommon.h
而 而不是 通常的 Rcpp.h
!!如果我们不在 Rcpp.h
调用之前放置前向声明,我们将无法正确注册我们的扩展。
然后,我们必须为 sourceCpp()
添加不同的插件标记,以便在代码编译期间设置适当的标志。在插件之后,我们将包括我们想要使用的实际提升 headers。最后,我们必须在 Rcpp::traits
命名空间中添加两个特殊的 Rcpp 函数声明,Rcpp::as<T>(obj)
和 Rcpp::wrap(obj)
。要启用多种类型,我们必须创建一个 Exporter
class 而不是更直接地调用 template <> ClassName as( SEXP )
。
#include <RcppCommon.h>
// Flags for C++ compiler
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins("cpp11")]]
// Third party library includes that provide the template class of ublas
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix.hpp>
// Provide Forward Declarations
namespace Rcpp {
namespace traits{
// Setup non-intrusive extension via template specialization for
// 'ublas' class boost::numeric::ublas
// Support for wrap
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj);
// Support for as<T>
template <typename T> class Exporter< boost::numeric::ublas::vector<T> >;
}
}
第 2 阶段 - 包括 Rcpp.h
有一个阶段只是为了声明导入顺序可能看起来很无聊,但是如果在前向声明之前包含 Rcpp.h
那么 Rcpp::traits
就不会更新,我们将进入深渊。
因此:
// >> Place <Rcpp.h> AFTER the forward declaration!!!! <<
#include <Rcpp.h>
// >> Place Definitions of Forward Declarations AFTER <Rcpp.h>!!!! <<
第 3 阶段 - 实施扩展
现在,我们必须实际执行前向声明。特别是,唯一会有点问题的实现是 as<>
,因为 wrap()
是直截了当的。
wrap()
要实现 wrap()
,我们必须在 Rcpp 中调用一个名为 Rcpp::traits::r_sexptype_traits<T>::rtype
的内置类型转换索引。由此,我们可以得到一个包含RTYPE
的int
,然后构造一个Rcpp::Vector
。对于矩阵的构造,同样的道理。
as()
对于as<>()
,我们需要考虑传入的模板。此外,我们在Exporter
class定义的正下方设置了一个typedef
,以方便定义要在 get()
方法中使用的 OUT
object。除此之外,我们使用相同的技巧在 C++ T
类型和 R
类型之间来回移动。
为了完成 as<>
,或者从 R 到 C++ 的直接端口,我不得不做一些肮脏的事情:我复制了向量内容。管理此输出的代码在 Exporter
class 的 get()
中给出。您可能希望花一些时间研究使用指针更改分配。我不是很精通 ublas
所以我没有看到解决指针传递的简单方法。
// Define template specializations for as<> and wrap
namespace Rcpp {
namespace traits{
// Defined wrap case
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj){
const int RTYPE = Rcpp::traits::r_sexptype_traits<T>::rtype ;
return Rcpp::Vector< RTYPE >(obj.begin(), obj.end());
};
// Defined as< > case
template<typename T>
class Exporter< boost::numeric::ublas::vector<T> > {
typedef typename boost::numeric::ublas::vector<T> OUT ;
// Convert the type to a valid rtype.
const static int RTYPE = Rcpp::traits::r_sexptype_traits< T >::rtype ;
Rcpp::Vector<RTYPE> vec;
public:
Exporter(SEXP x) : vec(x) {
if (TYPEOF(x) != RTYPE)
throw std::invalid_argument("Wrong R type for mapped 1D array");
}
OUT get() {
// Need to figure out a way to perhaps do a pointer pass?
OUT x(vec.size());
std::copy(vec.begin(), vec.end(), x.begin()); // have to copy data
return x;
}
} ;
}
}
第 4 阶段 - 测试
好吧,让我们看看我们所做的工作是否得到了回报(剧透它做到了!剧透)。要检查,我们应该查看两个不同的区域:
- 函数内的跟踪诊断;
- 自动测试。
两者都在下面给出。请注意,我选择将 ublas
设置缩短为:
// Here we define a shortcut to the boost ublas class to enable multiple ublas types via a template.
// ublas::vector<T> => ublas::vector<double>, ... , ublas::vector<int>
namespace ublas = ::boost::numeric::ublas;
跟踪诊断
// [[Rcpp::export]]
void containment_test(Rcpp::NumericVector x1) {
Rcpp::Rcout << "Converting from Rcpp::NumericVector to ublas::vector<double>" << std::endl;
ublas::vector<double> x = Rcpp::as< ublas::vector<double> >(x1); // initialize the vector to all zero
Rcpp::Rcout << "Running output test with ublas::vector<double>" << std::endl;
for (unsigned i = 0; i < x.size (); ++ i)
Rcpp::Rcout << x(i) << std::endl;
Rcpp::Rcout << "Converting from ublas::vector<double> to Rcpp::NumericVector" << std::endl;
Rcpp::NumericVector test = Rcpp::wrap(x);
Rcpp::Rcout << "Running output test with Rcpp::NumericVector" << std::endl;
for (unsigned i = 0; i < test.size (); ++ i)
Rcpp::Rcout << test(i) << std::endl;
}
测试调用:
containment_test(c(1,2,3,4))
结果:
Converting from Rcpp::NumericVector to ublas::vector<double>
Running output test with ublas::vector<double>
1
2
3
4
Converting from ublas::vector<double> to Rcpp::NumericVector
Running output test with Rcpp::NumericVector
1
2
3
4
此测试按预期执行。进入下一个测试!
自动测试
// [[Rcpp::export]]
ublas::vector<double> automagic_ublas_rcpp(ublas::vector<double> x1) {
return x1;
}
测试调用:
automagic_ublas_rcpp(c(1,2,3.2,1.2))
结果:
[1] 1.0 2.0 3.2 1.2
成功!
第 5 阶段 - Cntrl + C 和 Cntrl + V
这里是阶段给出的上述代码块的组合。如果您将其复制并粘贴到您的 .cpp
文件中,那么一切 都应该 有效。如果没有,请告诉我。
// -------------- Stage 1: Forward Declarations with `RcppCommon.h`
#include <RcppCommon.h>
// Flags for C++ compiler
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins("cpp11")]]
// Third party library includes that provide the template class of ublas
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/matrix.hpp>
// Here we use ublas_vec to enable multiple ublas types via a template.
// ublas::vector<T> => ublas::vector<double>, ... , ublas::vector<int>
namespace ublas = ::boost::numeric::ublas;
// Provide Forward Declarations
namespace Rcpp {
namespace traits{
// Setup non-intrusive extension via template specialization for
// 'ublas' class boost::numeric::ublas
// Support for wrap
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj);
// Support for as<T>
template <typename T> class Exporter< boost::numeric::ublas::vector<T> >;
}
}
// -------------- Stage 2: Including Rcpp.h
// >> Place <Rcpp.h> AFTER the forward declaration!!!! <<
#include <Rcpp.h>
// >> Place Definitions of Forward Declarations AFTER <Rcpp.h>!!!! <<
// -------------- Stage 3: Implementation of Declarations
// Define template specializations for as<> and wrap
namespace Rcpp {
namespace traits{
// Defined wrap case
template <typename T> SEXP wrap(const boost::numeric::ublas::vector<T> & obj){
const int RTYPE = Rcpp::traits::r_sexptype_traits<T>::rtype ;
return Rcpp::Vector< RTYPE >(obj.begin(), obj.end());
};
// Defined as< > case
template<typename T>
class Exporter< boost::numeric::ublas::vector<T> > {
typedef typename boost::numeric::ublas::vector<T> OUT ;
// Convert the type to a valid rtype.
const static int RTYPE = ::Rcpp::traits::r_sexptype_traits< T >::rtype ;
Rcpp::Vector<RTYPE> vec;
public:
Exporter(SEXP x) : vec(x) {
if (TYPEOF(x) != RTYPE)
throw std::invalid_argument("Wrong R type for mapped 1D array");
}
OUT get() {
// Need to figure out a way to perhaps do a pointer pass?
OUT x(vec.size());
std::copy(vec.begin(), vec.end(), x.begin()); // have to copy data
return x;
}
} ;
}
}
// -------------- Stage 4: Tests
// [[Rcpp::export]]
ublas::vector<double> automagic_ublas_rcpp(ublas::vector<double> x1) {
return x1;
}
// [[Rcpp::export]]
void containment_test(Rcpp::NumericVector x1) {
Rcpp::Rcout << "Converting from Rcpp::NumericVector to ublas::vector<double>" << std::endl;
ublas::vector<double> x = Rcpp::as< ublas::vector<double> >(x1); // initialize the vector to all zero
Rcpp::Rcout << "Running output test with ublas::vector<double>" << std::endl;
for (unsigned i = 0; i < x.size (); ++ i)
Rcpp::Rcout << x(i) << std::endl;
Rcpp::Rcout << "Converting from ublas::vector<double> to Rcpp::NumericVector" << std::endl;
Rcpp::NumericVector test = Rcpp::wrap(x);
Rcpp::Rcout << "Running output test with Rcpp::NumericVector" << std::endl;
for (unsigned i = 0; i < test.size (); ++ i)
Rcpp::Rcout << test(i) << std::endl;
}
结束语
哇...那太多了。希望以上内容提供了足够的理由,因为我相信您可能希望将 1D
向量扩展到 ublas::matrix
等等。此外,等待应该是值得的,因为您现在拥有 Rcpp
的自动转换魔法,因此无需在 return()
语句中调用 ublas2rcpp()
。事实上,您可以将函数的 return 类型简化为 ublas::vector<double>
!
在其他新闻中,我认为可能是什么阻止了您的创作上面的备用模板函数(例如 rcpp2ublas
)无法推断出 Rcpp::Vector
是什么 C++ T
类型。就我个人而言,在 Rcpp GitHub Repo 中仔细研究之后,我不确定是否存在这样的转换索引,或者由于 Shield
的用法,是否应该使用它。深入挖掘转化是另一天的冒险。