R Rcpp big.matrix加入

时间:2014-10-30 14:45:08

标签: c++ r rcpp r-bigmemory

我正在尝试为R中的big.matrix对象实现一些基本的C ++代码。我正在使用Rcpp包,已经阅读了演示here甚至应用了我在{{3上找到的另一个简单函数}}:

#include "bigmemory/BigMatrix.h"
#include "bigmemory/MatrixAccessor.hpp"
#include <Rcpp.h>

using namespace Rcpp;

// [[Rcpp::export]]
void fun(SEXP A) {
    Rcpp::XPtr<BigMatrix> bigMat(A);
    MatrixAccessor<int> Am(*bigMat);

    int nrows = bigMat->nrow();
    int ncolumns = bigMat->ncol();
    for (int j = 0; j < ncolumns; j++){
      for (int i = 1; i < nrows; i++){
                Am[j][i] = Am[j][i] + Am[j][i-1];
            }
    }
    return;
}

// [[Rcpp::export]]
void BigTranspose(SEXP A)
{
    Rcpp::XPtr<BigMatrix> pMat(A);
    MatrixAccessor<int> mat(*pMat);

    int r = pMat->nrow();
    int c = pMat->ncol();

    for(int i=0; i<r; ++i)
      for(int j=0; j<c; ++j)
        std::swap(mat[j][i], mat[i][j]);

    return;
}

这个fun函数完全正常,修改了big.matrix对象。

a <- matrix(seq(25), 5,5)
> a
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25
> fun(b@address)
> head(b)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    3   13   23   33   43
[3,]    6   21   36   51   66
[4,]   10   30   50   70   90
[5,]   15   40   65   90  115

然而,当我尝试简单的方阵转置函数时,矩阵不会被修改。为什么fun函数可以工作而不是我的'BigTranspose`?

a <- matrix(seq(25), 5,5)
> a
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25
b <- as.big.matrix(a)
BigTranspose(b@address)
> head(b)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

1 个答案:

答案 0 :(得分:2)

问题在于转置算法;您正在循环遍历所有行和列,因此正在重新交换swap。您可以通过将j的较低索引设置为j = i+1而不是j = 0来解决此问题:

#include "bigmemory/BigMatrix.h"
#include "bigmemory/MatrixAccessor.hpp"
#include <Rcpp.h>
// [[Rcpp::depends(BH, bigmemory)]]
using namespace Rcpp;

// [[Rcpp::export]]
void BigTranspose(SEXP A)
{
    Rcpp::XPtr<BigMatrix> pMat(A);
    MatrixAccessor<int> mat(*pMat);

    int r = pMat->nrow();
    int c = pMat->ncol();

    for(int i=0; i<r; i++){
      for(int j=0; j<c; j++){
        std::swap(mat[j][i], mat[i][j]);
      }
    }
    return;
}

// [[Rcpp::export]]
void BigTranspose2(SEXP A)
{
    Rcpp::XPtr<BigMatrix> pMat(A);
    MatrixAccessor<int> mat(*pMat);

    int r = pMat->nrow();
    int c = pMat->ncol();

    for(int i=0; i<r; i++){
      for(int j=(i+1); j<c; j++){
        std::swap(mat[j][i], mat[i][j]);
      }
    }
    return;
}

/*** R
##
b1 <- as.big.matrix(a)
head(b1)
##
BigTranspose(b1@address)
head(b1)
##
##
b2 <- as.big.matrix(a)
head(b2)
##
BigTranspose2(b2@address)
head(b2)
##
##
M <- matrix(1:25,ncol=5)
t(M)
##
*/

通过将BigTranspose2的输出与t(M)的输出进行比较,您可以看到第二个版本正常工作,其中Mmatrix等效的b1 }和b2

> Rcpp::sourceCpp('bigMatTranspose.cpp')

> b1 <- as.big.matrix(a)

> head(b1)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

> ##
> BigTranspose(b1@address)

> head(b1)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

> ##
> ##
> b2 <- as.big.matrix(a)

> head(b2)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

> ##
> BigTranspose2(b2@address)

> head(b2)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
[4,]   16   17   18   19   20
[5,]   21   22   23   24   25

> ##
> ##
> M <- matrix(1:25,ncol=5)

> t(M)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
[4,]   16   17   18   19   20
[5,]   21   22   23   24   25

请注意,这对于方形矩阵可以正常工作,但您必须对其进行一些修改才能使用任意维度的矩阵。