diff --git a/ChangeLog b/ChangeLog index 334f12794..0fdddac43 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2017-11-05 Daniel C. Dillon + + * inst/include/Rcpp/vector/Vector.h: Added inject() and extract() + functions to allow insertion and retrieval of raw C++ data into + and from Rcpp::Vector of arithmetic types. + * inst/unitTests/cpp/Vector.cpp: Unit tests + * inst/unitTests/runit.Vector.R: Unit tests + 2017-11-04 Dirk Eddelbuettel * vignettes/Rcpp-FAQ.Rmd: Add 'skip_final_break: true' toggle diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 406332c4e..fa403387d 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -13,7 +13,9 @@ allocating one (Kirill Müller in \ghpr{763}). \item New \code{DateVector} and \code{DatetimeVector} classes are now the default fully deprecating the old classes as announced one year ago. - + \item New \code{Vector::inject()} and \code{Vector::extract()} functions + for copying raw byte data from C++ into an element or elements in + \code{Vector}. } \item Changes in Rcpp Package: \itemize{ diff --git a/inst/include/Rcpp/vector/Vector.h b/inst/include/Rcpp/vector/Vector.h index 141bce006..eadafaa71 100644 --- a/inst/include/Rcpp/vector/Vector.h +++ b/inst/include/Rcpp/vector/Vector.h @@ -374,6 +374,59 @@ class Vector : return NameProxy( const_cast(*this), name ) ; } + template< typename T > + inline typename traits::enable_if< + traits::is_arithmetic< stored_type >::value + && sizeof(T) <= sizeof(stored_type), void >::type + inject(R_xlen_t i, const T &val) { + std::memcpy(&cache.ref(offset(i)), &val, sizeof(T)); + } + + template< typename T > + inline typename traits::enable_if< + traits::is_arithmetic< stored_type >::value + && sizeof(T) == sizeof(stored_type), void >::type + inject(R_xlen_t start, const T *val, std::size_t len) { + std::memcpy(&cache.ref(offset(start)), val, sizeof(T) * len); + } + + template< typename T > + inline typename traits::enable_if< + traits::is_arithmetic< stored_type >::value + && sizeof(T) < sizeof(stored_type), void >::type + inject(R_xlen_t start, const T *val, std::size_t len) { + for (std::size_t i = 0; i < len; ++i) { + inject(start + i, *(val + i)); + } + } + + template< typename T > + inline typename traits::enable_if< + traits::is_arithmetic< stored_type >::value + && sizeof(stored_type) >= sizeof(T), void >::type + extract(R_xlen_t i, T &val) { + std::memcpy(&val, &cache.ref(offset(i)), sizeof(T)); + } + + template< typename T > + inline typename traits::enable_if< + traits::is_arithmetic< stored_type >::value + && sizeof(stored_type) == sizeof(T), void >::type + extract(R_xlen_t start, T *val, std::size_t len) { + std::memcpy(val, &cache.ref(offset(start)), + sizeof(stored_type) * len); + } + + template< typename T > + inline typename traits::enable_if< + traits::is_arithmetic< stored_type >::value + && sizeof(T) < sizeof(stored_type), void >::type + extract(R_xlen_t start, T *val, std::size_t len) { + for (std::size_t i = 0; i < len; ++i) { + extract(start + i, *(val + i)); + } + } + inline operator RObject() const { return RObject( Storage::get__() ); } diff --git a/inst/unitTests/cpp/Vector.cpp b/inst/unitTests/cpp/Vector.cpp index 2c47b7e7a..db7100247 100644 --- a/inst/unitTests/cpp/Vector.cpp +++ b/inst/unitTests/cpp/Vector.cpp @@ -848,3 +848,75 @@ String vec_print_integer(IntegerVector v) { IntegerVector vec_subset(IntegerVector x, IntegerVector y) { return x[y - 1]; } + +// [[Rcpp::export]] +NumericVector vec_inject() { + int64_t i = 12345; + int64_t ii = 9876543210; + + NumericVector v(2); + + v.inject(0, i); + v.inject(1, ii); + + return v; +} + +// [[Rcpp::export]] +NumericVector vec_inject_array() { + const int64_t arr[] = { 12345, 9876543210 }; + + NumericVector v(2); + v.inject(0, arr, 2); + + return v; +} + +// [[Rcpp::export]] +NumericVector vec_inject_array_smaller() { + const int32_t arr[] = { 12345, 98765432 }; + + NumericVector v(2); + v.inject(0, arr, 2); + + return v; +} + +// [[Rcpp::export]] +NumericVector vec_extract(NumericVector v) { + int64_t i; + int64_t ii; + + v.extract(0, i); + v.extract(1, ii); + + NumericVector v2(2); + v2.inject(0, i); + v2.inject(1, ii); + + return v2; +} + +// [[Rcpp::export]] +NumericVector vec_extract_array(NumericVector v) { + int64_t i[2]; + + v.extract(0, i, 2); + + NumericVector v2(2); + v2.inject(0, i, 2); + + return v2; +} + +// [[Rcpp::export]] +NumericVector vec_extract_array_smaller(NumericVector v) { + int32_t i[2]; + + v.extract(0, i, 2); + + NumericVector v2(2); + v2.inject(0, i, 2); + + return v2; +} diff --git a/inst/unitTests/runit.Vector.R b/inst/unitTests/runit.Vector.R index fdb0b0e58..25deb3c4f 100644 --- a/inst/unitTests/runit.Vector.R +++ b/inst/unitTests/runit.Vector.R @@ -755,5 +755,37 @@ if (.runThisTest) { gctorture(FALSE) checkEquals(x[y], z) } + + test.numeric.vector.inject <- function() { + v <- vec_inject() + checkIdentical(v, c(6.0992403979101885879e-320, + 4.8796606997276282938e-314)) + } + + test.numeric.vector.inject.array <- function() { + v <- vec_inject_array() + checkIdentical(v, c(6.0992403979101885879e-320, + 4.8796606997276282938e-314)) + } + + test.numeric.vector.inject.extract.array.smaller <- function() { + v <- vec_inject_array_smaller() + v2 <- vec_extract_array_smaller(v) + checkIdentical(v, v2) + } + + test.numeric.vector.extract <- function() { + v <- c(6.0992403979101885879e-320, 4.8796606997276282938e-314) + + res <- vec_extract(v) + checkIdentical(v, res) + } + + test.numeric.vector.extract_array <- function() { + v <- c(6.0992403979101885879e-320, 4.8796606997276282938e-314) + + res <- vec_extract_array(v) + checkIdentical(v, res) + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy