diff --git a/R/RcppExports.R b/R/RcppExports.R
index f5af029..e8f2962 100644
--- a/R/RcppExports.R
+++ b/R/RcppExports.R
@@ -41,6 +41,10 @@ bitset_or <- function(a, b) {
invisible(.Call(`_individual_bitset_or`, a, b))
}
+bitset_copy_from <- function(a, b) {
+ invisible(.Call(`_individual_bitset_copy_from`, a, b))
+}
+
bitset_xor <- function(a, b) {
invisible(.Call(`_individual_bitset_xor`, a, b))
}
diff --git a/R/bitset.R b/R/bitset.R
index 0a2db18..7c551a8 100644
--- a/R/bitset.R
+++ b/R/bitset.R
@@ -210,10 +210,28 @@ Bitset <- list(
#' ```{r echo=FALSE, results="asis"}
#' bitset_method_doc(
#' "copy",
- #' "returns a copy of the bitset.")
+ #' "returns a copy of the bitset.
+ #'
+ #' In cases where a destination bitset already exists, it may be more
+ #' performant to use the \\code{copy_from} method instead.")
#' ```
copy = function() Bitset$new(from = bitset_copy(self$.bitset)),
+
+ #' ```{r echo=FALSE, results="asis"}
+ #' bitset_method_doc(
+ #' "copy_from",
+ #' "overwrite the value of the bitset from another bitset.
+ #'
+ #' This is similar to calling \\code{other$copy()}, but can be more
+ #' efficient by reusing the resources of the existing bitset.",
+ #' other = "the other bitset.")
+ #' ```
+ copy_from = function(other) {
+ bitset_copy_from(self$.bitset, other$.bitset)
+ self
+ },
+
#' ```{r echo=FALSE, results="asis"}
#' bitset_method_doc(
#' "to_vector",
diff --git a/man/Bitset.Rd b/man/Bitset.Rd
index 9955742..22b97c9 100644
--- a/man/Bitset.Rd
+++ b/man/Bitset.Rd
@@ -160,11 +160,29 @@ k should be chosen such that \eqn{0 \le k \le N}.}
\if{html}{\out{
}}
\subsection{Method \code{copy()}}{
returns a copy of the bitset.
+
+In cases where a destination bitset already exists, it may be more
+performant to use the \code{copy_from} method instead.
\subsection{Usage}{
\preformatted{b$copy()}
}
}
\if{html}{\out{
}}
+\subsection{Method \code{copy_from()}}{
+overwrite the value of the bitset from another bitset.
+
+This is similar to calling \code{other$copy()}, but can be more
+efficient by reusing the resources of the existing bitset.
+\subsection{Usage}{
+\preformatted{b$copy_from(other)}
+}
+\subsection{Arguments}{
+\describe{
+\item{\code{other}}{the other bitset.}
+}
+}
+}
+\if{html}{\out{
}}
\subsection{Method \code{to_vector()}}{
return an integer vector of the elements stored in this bitset.
\subsection{Usage}{
diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp
index 560ac8d..1c5e23d 100644
--- a/src/RcppExports.cpp
+++ b/src/RcppExports.cpp
@@ -124,6 +124,17 @@ BEGIN_RCPP
return R_NilValue;
END_RCPP
}
+// bitset_copy_from
+void bitset_copy_from(const Rcpp::XPtr a, const Rcpp::XPtr b);
+RcppExport SEXP _individual_bitset_copy_from(SEXP aSEXP, SEXP bSEXP) {
+BEGIN_RCPP
+ Rcpp::RNGScope rcpp_rngScope_gen;
+ Rcpp::traits::input_parameter< const Rcpp::XPtr >::type a(aSEXP);
+ Rcpp::traits::input_parameter< const Rcpp::XPtr >::type b(bSEXP);
+ bitset_copy_from(a, b);
+ return R_NilValue;
+END_RCPP
+}
// bitset_xor
void bitset_xor(const Rcpp::XPtr a, const Rcpp::XPtr b);
RcppExport SEXP _individual_bitset_xor(SEXP aSEXP, SEXP bSEXP) {
@@ -1476,6 +1487,7 @@ static const R_CallMethodDef CallEntries[] = {
{"_individual_bitset_and", (DL_FUNC) &_individual_bitset_and, 2},
{"_individual_bitset_not", (DL_FUNC) &_individual_bitset_not, 2},
{"_individual_bitset_or", (DL_FUNC) &_individual_bitset_or, 2},
+ {"_individual_bitset_copy_from", (DL_FUNC) &_individual_bitset_copy_from, 2},
{"_individual_bitset_xor", (DL_FUNC) &_individual_bitset_xor, 2},
{"_individual_bitset_set_difference", (DL_FUNC) &_individual_bitset_set_difference, 2},
{"_individual_bitset_sample", (DL_FUNC) &_individual_bitset_sample, 2},
diff --git a/src/bitset.cpp b/src/bitset.cpp
index dbabdce..aec4f9b 100644
--- a/src/bitset.cpp
+++ b/src/bitset.cpp
@@ -88,6 +88,17 @@ void bitset_or(
(*a) |= (*b);
}
+//[[Rcpp::export]]
+void bitset_copy_from(
+ const Rcpp::XPtr a,
+ const Rcpp::XPtr b
+ ) {
+ if (a->max_size() != b->max_size()) {
+ Rcpp::stop("Incompatible bitmap sizes");
+ }
+ (*a) = (*b);
+}
+
//[[Rcpp::export]]
void bitset_xor(
const Rcpp::XPtr a,
diff --git a/tests/testthat/test-bitset.R b/tests/testthat/test-bitset.R
index ebed57b..888bdce 100644
--- a/tests/testthat/test-bitset.R
+++ b/tests/testthat/test-bitset.R
@@ -80,6 +80,31 @@ test_that("bitset or works", {
expect_equal(a$to_vector(), c(1, 3, 5, 6, 7))
})
+test_that("bitset copy from works", {
+ a <- Bitset$new(10)
+ a$insert(c(1, 5, 6))
+ b <- Bitset$new(10)
+ b$insert(c(1, 3, 7))
+
+ a$copy_from(b)
+ expect_equal(a$to_vector(), c(1, 3, 7))
+
+ # Check the two bitsets aren't aliases of each other.
+ b$clear()
+ expect_equal(a$to_vector(), c(1, 3, 7))
+ expect_equal(b$to_vector(), numeric(0))
+})
+
+test_that("bitset copy from requires bitsets to have same max size", {
+ a <- Bitset$new(8)
+ a$insert(c(1, 5, 6))
+ b <- Bitset$new(10)
+ b$insert(c(1, 3, 7))
+
+ expect_error(a$copy_from(b), "Incompatible bitmap sizes")
+})
+
+
test_that("bitset set difference works for sets with intersection", {
a <- Bitset$new(20)