Dear all,
I have made the following primitive "concatenate" function, because I couldn't find one in Rcpp:
template <const int RTYPE>
Vector<RTYPE> do_conc_(Vector<RTYPE> x, Vector<RTYPE> y){
int nx=x.size(), n=x.size()+y.size(),i,j;
Vector<RTYPE> out=no_init(n);
for (i=0; i<nx; ++i){ out[ i ] = x[ i ];}
for (j=i, i=0; j<n; ++j, ++i){ out[ j ] = y[i] ;}
return out;
}
// [[Rcpp::export]]
SEXP conc( SEXP& XX_, SEXP& YY_){
int type = TYPEOF(XX_) ;
switch( type ){
case INTSXP : return do_conc_<INTSXP> ( XX_, YY_ ) ;
case REALSXP : return do_conc_<REALSXP>( XX_, YY_ ) ;
case STRSXP : return do_conc_<STRSXP> ( XX_, YY_ ) ;
case VECSXP : return do_conc_<VECSXP> ( XX_, YY_ ) ;
}
return R_NilValue ;
}
As you can see it assumes that the two inputs XX_ and YY_ are of the same type, and it fails to copy names to the output. If I have missed any such functionality in Rcpp then I would be happy to know...
Cheers
S?ren
[Rcpp-devel] Rcpp version of c( )
7 messages · Søren Højsgaard, Kevin Ushey, Romain Francois +1 more
Hi S?ren,
I like the idea. Currently there is nothing like that in Rcpp. It
could be made more flexible if we:
1. Accept a generic set of vectors that could be appropriately casted as needed,
2. Cast these vectors to the appropriate type if necessary,
3. Fill an output vector with the elements of these vectors.
Of course, we would like to be able to accept primitives as well so
that e.g. c(x, 1, y) works so something a bit more designed would be
nice.
There should be a flexible way to implement this using variadic
templates, so that e.g.
template <typename T, typename... Args>
T c( Args... args ) {
...do the concatenation...
}
Of course, this requires C++11 so it might not fit until R 3.1.0 is
out with its C++11 support, but it could be a natural fit in Rcpp11.
Adding the generic version in Rcpp would require code bloat
unfortunately.
-Kevin
On Tue, Jan 21, 2014 at 2:02 PM, S?ren H?jsgaard <sorenh at math.aau.dk> wrote:
Dear all,
I have made the following primitive "concatenate" function, because I couldn't find one in Rcpp:
template <const int RTYPE>
Vector<RTYPE> do_conc_(Vector<RTYPE> x, Vector<RTYPE> y){
int nx=x.size(), n=x.size()+y.size(),i,j;
Vector<RTYPE> out=no_init(n);
for (i=0; i<nx; ++i){ out[ i ] = x[ i ];}
for (j=i, i=0; j<n; ++j, ++i){ out[ j ] = y[i] ;}
return out;
}
// [[Rcpp::export]]
SEXP conc( SEXP& XX_, SEXP& YY_){
int type = TYPEOF(XX_) ;
switch( type ){
case INTSXP : return do_conc_<INTSXP> ( XX_, YY_ ) ;
case REALSXP : return do_conc_<REALSXP>( XX_, YY_ ) ;
case STRSXP : return do_conc_<STRSXP> ( XX_, YY_ ) ;
case VECSXP : return do_conc_<VECSXP> ( XX_, YY_ ) ;
}
return R_NilValue ;
}
As you can see it assumes that the two inputs XX_ and YY_ are of the same type, and it fails to copy names to the output. If I have missed any such functionality in Rcpp then I would be happy to know...
Cheers
S?ren
_______________________________________________ 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
Hi,
There is currently nothing like that. It is quite hard to generalize.
You might like std::merge, e.g.
template <typename Vec>
Vec do_conc_(Vec x, Vec y){
Vec out=no_init(x.size()+y.size());
std::merge( x.begin(), x.end(), y.begin(), y.end(), out.begin() ) ;
return out;
}
We could want to generalize this to arbitrary sugar expressions, so that we could do e.g.
conc( x+x, y+y ) ;
without having to materialize x+x and y+y into their own memory ...
Perhaps it would look like this:
template <int RTYPE, typename T1, typename T2>
Vector<RTYPE> concat( const T1& t1, const T2& t2 ){
// use static_assert to make sure T1 and T2 are sugar expressions
int n = t1.size() + t2.size() ;
Vector<RTYPE> out = no_init(n) ;
std::merge( t1.begin(), t1.end(), t2.begin(), t2.end(), out.begin() ) ;
return out ;
}
Then as Kevin hints (and has opened an issue in https://github.com/romainfrancois/Rcpp11/issues/92) we can want to go further and want something with multiple inputs.
Interesting idea, I guess lots of work to generalize it.
Romain
Le 21 janv. 2014 ? 23:02, S?ren H?jsgaard <sorenh at math.aau.dk> a ?crit :
Dear all,
I have made the following primitive "concatenate" function, because I couldn't find one in Rcpp:
template <const int RTYPE>
Vector<RTYPE> do_conc_(Vector<RTYPE> x, Vector<RTYPE> y){
int nx=x.size(), n=x.size()+y.size(),i,j;
Vector<RTYPE> out=no_init(n);
for (i=0; i<nx; ++i){ out[ i ] = x[ i ];}
for (j=i, i=0; j<n; ++j, ++i){ out[ j ] = y[i] ;}
return out;
}
// [[Rcpp::export]]
SEXP conc( SEXP& XX_, SEXP& YY_){
int type = TYPEOF(XX_) ;
switch( type ){
case INTSXP : return do_conc_<INTSXP> ( XX_, YY_ ) ;
case REALSXP : return do_conc_<REALSXP>( XX_, YY_ ) ;
case STRSXP : return do_conc_<STRSXP> ( XX_, YY_ ) ;
case VECSXP : return do_conc_<VECSXP> ( XX_, YY_ ) ;
}
return R_NilValue ;
}
As you can see it assumes that the two inputs XX_ and YY_ are of the same type, and it fails to copy names to the output. If I have missed any such functionality in Rcpp then I would be happy to know...
Cheers
S?ren
Hi Kevin,
Thanks for your reply. I was only introduced to C++11 last week (my fault!); it seems that everybodys life becomes much easier once R-packages can be made with that...
I think many Rcpp-friends would welcome a version of c( ). One view is of course that it should be as general as R's c( )-function. A more pragmatic view is a version of c() that could concatenate (a) two lists and (b) two vectors (where each can be integers, doubles, characters and complex, independently of each other). I guess that would satisfy 90+% of the needs for a c( ) function in an Rcpp setting...
Best regards
S?ren
-----Original Message-----
From: Kevin Ushey [mailto:kevinushey at gmail.com]
Sent: 22. januar 2014 01:10
To: S?ren H?jsgaard
Cc: rcpp-devel at lists.r-forge.r-project.org (rcpp-devel at r-forge.wu-wien.ac.at)
Subject: Re: [Rcpp-devel] Rcpp version of c( )
Hi S?ren,
I like the idea. Currently there is nothing like that in Rcpp. It could be made more flexible if we:
1. Accept a generic set of vectors that could be appropriately casted as needed, 2. Cast these vectors to the appropriate type if necessary, 3. Fill an output vector with the elements of these vectors.
Of course, we would like to be able to accept primitives as well so that e.g. c(x, 1, y) works so something a bit more designed would be nice.
There should be a flexible way to implement this using variadic templates, so that e.g.
template <typename T, typename... Args>
T c( Args... args ) {
...do the concatenation...
}
Of course, this requires C++11 so it might not fit until R 3.1.0 is out with its C++11 support, but it could be a natural fit in Rcpp11.
Adding the generic version in Rcpp would require code bloat unfortunately.
-Kevin
On Tue, Jan 21, 2014 at 2:02 PM, S?ren H?jsgaard <sorenh at math.aau.dk> wrote:
Dear all,
I have made the following primitive "concatenate" function, because I couldn't find one in Rcpp:
template <const int RTYPE>
Vector<RTYPE> do_conc_(Vector<RTYPE> x, Vector<RTYPE> y){
int nx=x.size(), n=x.size()+y.size(),i,j;
Vector<RTYPE> out=no_init(n);
for (i=0; i<nx; ++i){ out[ i ] = x[ i ];}
for (j=i, i=0; j<n; ++j, ++i){ out[ j ] = y[i] ;}
return out;
}
// [[Rcpp::export]]
SEXP conc( SEXP& XX_, SEXP& YY_){
int type = TYPEOF(XX_) ;
switch( type ){
case INTSXP : return do_conc_<INTSXP> ( XX_, YY_ ) ;
case REALSXP : return do_conc_<REALSXP>( XX_, YY_ ) ;
case STRSXP : return do_conc_<STRSXP> ( XX_, YY_ ) ;
case VECSXP : return do_conc_<VECSXP> ( XX_, YY_ ) ;
}
return R_NilValue ;
}
As you can see it assumes that the two inputs XX_ and YY_ are of the same type, and it fails to copy names to the output. If I have missed any such functionality in Rcpp then I would be happy to know...
Cheers
S?ren
_______________________________________________ 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-deve l
Le 22 janv. 2014 ? 01:10, Kevin Ushey <kevinushey at gmail.com> a ?crit :
Hi S?ren, I like the idea. Currently there is nothing like that in Rcpp. It could be made more flexible if we: 1. Accept a generic set of vectors that could be appropriately casted as needed, 2. Cast these vectors to the appropriate type if necessary, 3. Fill an output vector with the elements of these vectors. Of course, we would like to be able to accept primitives as well so that e.g. c(x, 1, y) works so something a bit more designed would be nice.
there is also the problem of names, e.g. c(x, foo = 1, y). This is a big part of the problem with ::create As a first approximation, perhaps we could ignore names.
There should be a flexible way to implement this using variadic
templates, so that e.g.
template <typename T, typename... Args>
T c( Args... args ) {
...do the concatenation?
}
I?ll discuss more on the issue you opened or if you create a branch for the feature in Rcpp11. I guess the R type must play a role, so I?d imagine an interface more like this :
template <int RTYPE, typename... Args>
Vector<RTYPE> c( Args... args ) {
static_assert( all types in Args are compatible with RTYPE )
- find the final length
- allocate a vector of that length
- recursively iterate through args
}
Once you understand them, variadic templates are quite fun to work with. On a related note, I?ve added a structure function recently to Rcpp11.
Of course, this requires C++11 so it might not fit until R 3.1.0 is out with its C++11 support, but it could be a natural fit in Rcpp11. Adding the generic version in Rcpp would require code bloat unfortunately.
This might be fun to produce with C++11, but a massive pain with C++98. Romain
-Kevin On Tue, Jan 21, 2014 at 2:02 PM, S?ren H?jsgaard <sorenh at math.aau.dk> wrote:
Dear all,
I have made the following primitive "concatenate" function, because I couldn't find one in Rcpp:
template <const int RTYPE>
Vector<RTYPE> do_conc_(Vector<RTYPE> x, Vector<RTYPE> y){
int nx=x.size(), n=x.size()+y.size(),i,j;
Vector<RTYPE> out=no_init(n);
for (i=0; i<nx; ++i){ out[ i ] = x[ i ];}
for (j=i, i=0; j<n; ++j, ++i){ out[ j ] = y[i] ;}
return out;
}
// [[Rcpp::export]]
SEXP conc( SEXP& XX_, SEXP& YY_){
int type = TYPEOF(XX_) ;
switch( type ){
case INTSXP : return do_conc_<INTSXP> ( XX_, YY_ ) ;
case REALSXP : return do_conc_<REALSXP>( XX_, YY_ ) ;
case STRSXP : return do_conc_<STRSXP> ( XX_, YY_ ) ;
case VECSXP : return do_conc_<VECSXP> ( XX_, YY_ ) ;
}
return R_NilValue ;
}
As you can see it assumes that the two inputs XX_ and YY_ are of the same type, and it fails to copy names to the output. If I have missed any such functionality in Rcpp then I would be happy to know...
Cheers
S?ren
_______________________________________________ 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
_______________________________________________ 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
Hi,
There is a preliminary version of this in Rcpp11. For example:
#include <Rcpp.h>
using namespace Rcpp ;
// [[Rcpp::export]]
NumericVector test(){
NumericVector x(10) ;
NumericVector y(30) ;
return NumericVector::concat(x, 2.0, y, 1.0) ;
}
So it handles (or at least it should):
- compatible primitive (i.e. double in the case of NumericVector)
- arbitrary compatible sugar expression
It is at least for now a static member function of the Vector class. Maybe it can be made a free function.
This is about 90 lines of C++11 code.
Romain
Le 22 janv. 2014 ? 01:37, S?ren H?jsgaard <sorenh at math.aau.dk> a ?crit :
Hi Kevin,
Thanks for your reply. I was only introduced to C++11 last week (my fault!); it seems that everybodys life becomes much easier once R-packages can be made with that...
I think many Rcpp-friends would welcome a version of c( ). One view is of course that it should be as general as R's c( )-function. A more pragmatic view is a version of c() that could concatenate (a) two lists and (b) two vectors (where each can be integers, doubles, characters and complex, independently of each other). I guess that would satisfy 90+% of the needs for a c( ) function in an Rcpp setting...
Best regards
S?ren
-----Original Message-----
From: Kevin Ushey [mailto:kevinushey at gmail.com]
Sent: 22. januar 2014 01:10
To: S?ren H?jsgaard
Cc: rcpp-devel at lists.r-forge.r-project.org (rcpp-devel at r-forge.wu-wien.ac.at)
Subject: Re: [Rcpp-devel] Rcpp version of c( )
Hi S?ren,
I like the idea. Currently there is nothing like that in Rcpp. It could be made more flexible if we:
1. Accept a generic set of vectors that could be appropriately casted as needed, 2. Cast these vectors to the appropriate type if necessary, 3. Fill an output vector with the elements of these vectors.
Of course, we would like to be able to accept primitives as well so that e.g. c(x, 1, y) works so something a bit more designed would be nice.
There should be a flexible way to implement this using variadic templates, so that e.g.
template <typename T, typename... Args>
T c( Args... args ) {
...do the concatenation...
}
Of course, this requires C++11 so it might not fit until R 3.1.0 is out with its C++11 support, but it could be a natural fit in Rcpp11.
Adding the generic version in Rcpp would require code bloat unfortunately.
-Kevin
On Tue, Jan 21, 2014 at 2:02 PM, S?ren H?jsgaard <sorenh at math.aau.dk> wrote:
Dear all,
I have made the following primitive "concatenate" function, because I couldn't find one in Rcpp:
template <const int RTYPE>
Vector<RTYPE> do_conc_(Vector<RTYPE> x, Vector<RTYPE> y){
int nx=x.size(), n=x.size()+y.size(),i,j;
Vector<RTYPE> out=no_init(n);
for (i=0; i<nx; ++i){ out[ i ] = x[ i ];}
for (j=i, i=0; j<n; ++j, ++i){ out[ j ] = y[i] ;}
return out;
}
// [[Rcpp::export]]
SEXP conc( SEXP& XX_, SEXP& YY_){
int type = TYPEOF(XX_) ;
switch( type ){
case INTSXP : return do_conc_<INTSXP> ( XX_, YY_ ) ;
case REALSXP : return do_conc_<REALSXP>( XX_, YY_ ) ;
case STRSXP : return do_conc_<STRSXP> ( XX_, YY_ ) ;
case VECSXP : return do_conc_<VECSXP> ( XX_, YY_ ) ;
}
return R_NilValue ;
}
As you can see it assumes that the two inputs XX_ and YY_ are of the same type, and it fails to copy names to the output. If I have missed any such functionality in Rcpp then I would be happy to know...
Cheers
S?ren
_______________________________________________ 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-deve l
_______________________________________________ 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
On 21 January 2014 at 22:02, S?ren H?jsgaard wrote:
| I have made the following primitive "concatenate" function, because I couldn't find one in Rcpp:
|
| template <const int RTYPE>
| Vector<RTYPE> do_conc_(Vector<RTYPE> x, Vector<RTYPE> y){
| int nx=x.size(), n=x.size()+y.size(),i,j;
| Vector<RTYPE> out=no_init(n);
| for (i=0; i<nx; ++i){ out[ i ] = x[ i ];}
| for (j=i, i=0; j<n; ++j, ++i){ out[ j ] = y[i] ;}
| return out;
| }
|
| // [[Rcpp::export]]
| SEXP conc( SEXP& XX_, SEXP& YY_){
| int type = TYPEOF(XX_) ;
| switch( type ){
| case INTSXP : return do_conc_<INTSXP> ( XX_, YY_ ) ;
| case REALSXP : return do_conc_<REALSXP>( XX_, YY_ ) ;
| case STRSXP : return do_conc_<STRSXP> ( XX_, YY_ ) ;
| case VECSXP : return do_conc_<VECSXP> ( XX_, YY_ ) ;
| }
| return R_NilValue ;
| }
|
| As you can see it assumes that the two inputs XX_ and YY_ are of the same type, and it fails to copy names to the output. If I have missed any such functionality in Rcpp then I would be happy to know...
My instinct would be to use RcppArmadillo vectors:
R> cppFunction("arma::colvec conc(const arma::colvec & x, const arma::colvec & y) { return arma::join_cols(x, y); }", depends="RcppArmadillo")
R> conc(1:3, 11:13)
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 11
[5,] 12
[6,] 13
R>
For more _generic_ solutions, the STL offers a lot.
Dirk
Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com