2015-06-10 26 views
2

RCPP交換功能正如我在探索RCPP我才意識到,下面的交換功能與NumericVector

// swap.cpp 
#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
void swap(NumericVector x) { 
    double tmp = x[0]; 
    x[0] = x[1]; 
    x[1] = tmp; 
} 

時傳遞了一個整數向量不進行交換。例如,

x <- 1:2 
str(x) 
# int [1:2] 1 2 
swap(x) 
x 
# [1] 1 2 

然而,

y <- c(1,2) 
str(y) 
# num [1:2] 1 2 
swap(y) 
y 
# [1] 2 1 

工作正常。我懷疑當swap通過一個整數向量x它被迫複製x轉換爲NumericVector。然後在x副本上執行的任何操作都不會影響傳遞的原始變量。這個推理是否正確?如果是這樣,爲什麼轉換必須產生副本?有沒有辦法寫一個更強大的swap函數,當我們應該傳遞一個數值向量時,我們不必擔心偶然傳遞一個整數向量?

我很抱歉如果這個問題以前曾被問過,但我找不到合適的答案。

編輯:

下面的代碼的確表明,當整數矢量被傳遞給swap而不是數字矢量對象的副本。

// [[Rcpp::export]] 
void where(SEXP x) { 
    Rcout << x << std::endl; 
} 

// [[Rcpp::export]] 
void swap(NumericVector x) { 
    double tmp = x[0]; 
    x[0] = x[1]; 
    x[1] = tmp; 
    Rcout << "During swap function: " << x << std::endl; 
} 

/*** R 
test_swap <- function(x) { 
    cat("Before the swap function: ") 
    cat(where(x)) 
    swap(x) 
    cat("After the swap function: ") 
    cat(where(x)) 
} 

y <- c(1, 2) // type num 
x <- 1:2 // type int 

test_swap(y) // swap works because type matches function 
#> Before the swap function: 0x116017bf8 
#> During swap function: 0x116017bf8 
#> After the swap function: 0x116017bf8 

test_swap(x) // swap does not work because type does not match function 
#> Before the swap function: 0x10d88e468 
#> During swap function: 0x116015708 
#> After the swap function: 0x10d88e468 
*/ 
+1

你說得對,轉換就是產生一個副本,使其無副作用。 Rcpp的一個優點是它不強制*在函數中新建數據。如果你想強制一個副本,你可以使用'y = clone(x)'並在'y'上操作。你可以閱讀[這些以前的SO問題](http://stackoverflow.com/search?q= [rcpp] +克隆)關於這個問題。 – r2evans

+0

謝謝@ r2evans,但我仍然不清楚如何在這種情況下編寫更強大的交換功能,我們不會遇到這個問題。 – Ramanudles

+2

只要你使用'NumericVector x',它總是會(a)爲你複製,或者(b)不會被複制給你,在你的代碼看到任何東西之前。您需要使用模板或'SEXP'將其設置爲通用,這兩者都顯示在[here](http://gallery.rcpp.org/articles/fast-factor-generation/)中。 – r2evans

回答

1

大廈@ r2evans的意見,這裏有一個最小的實現:

#include <Rcpp.h> 

template <int T> 
void swap_templ(Rcpp::Vector<T> x) { 
    double tmp = x[0]; 
    x[0] = x[1]; 
    x[1] = tmp; 
} 
// [[Rcpp::export]] 
void swap(SEXP x) { 
    switch (TYPEOF(x)) { 
    case INTSXP: 
    swap_templ<INTSXP>(x); 
    break; 
    case REALSXP: 
    swap_templ<REALSXP>(x); 
    break; 
    default: 
    Rcpp::Rcout << 
     "\nInput vector must be numeric or integer type" << 
     std::endl; 
    break; 
    } 
} 

/*** R 
iv <- 1L:3L 
dv <- 1:3 + 0.5 

R> class(iv) 
[1] "integer" 

R> class(dv) 
[1] "numeric" 

R> swap(iv); iv 
[1] 2 1 3 

R> swap(dv); dv 
[1] 2.5 1.5 3.5 

R> class(iv) 
[1] "integer" 

R> class(dv) 
[1] "numeric" 
*/ 
+0

只是沒有回來夠快...... :-) – r2evans