【问题标题】:Rcpp Compilation error with match()使用 match() 的 Rcpp 编译错误
【发布时间】:2016-02-19 04:07:57
【问题描述】:

我想对 ComplexVector 类型使用糖匹配函数,但出现错误

g++ -m64 -I"C:/PROGRA~1/R/R-32~1.3/include" -DNDEBUG     -I"*path*"
-I"*path*"  -I"d:/RCompile/r-compiling/local/local323/include"     
-O2 -Wall  -mtune=core2 -c setdiffComplexVectorsC.cpp 
-o setdiffComplexVectorsC.o
g++ -m64 -shared -s -static-libgcc -o sourceCpp_38.dll tmp.def 
setdiffComplexVectorsC.o -Ld:/RCompile/r-compiling/local/local323/lib/x64
-Ld:/RCompile/r-compiling/local/local323/lib 
-LC:/PROGRA~1/R/R-32~1.3/bin/x64 
-lR setdiffComplexVectorsC.o:setdiffComplexVectorsC.cpp:(.text+0x5e0):
 undefined reference to `Rcpp::sugar::IndexHash<15>::get_addr(Rcomplex) const'
setdiffComplexVectorsC.o:setdiffComplexVectorsC.cpp:(.text+0x788): undefined 
reference to `Rcpp::sugar::IndexHash<15>::get_addr(Rcomplex) const'
collect2: ld returned 1 exit status

Error in Rcpp::sourceCpp("setdiffComplexVectorsC.cpp") : 

**Error occurred building shared library.**

使用以下代码:

#include <Rcpp.h>
using namespace Rcpp;
using namespace std;
using namespace sugar;
// [[Rcpp::export]]
ComplexVector setdiffComplexVectorsC(ComplexVector        
ComplexVector2Curt,ComplexVector ComplexVector2compare){
// setdiffComplexVectors shortens ComplexVector2Curt by those rows that 
//are   in both matrices.
// INPUT
// ComplexVector2Curt(n)            complexvector, which will be shortened by ComplexVector2compare
// ComplexVector2compare(m)         complexvector whose elements will be compared to those of ComplexVector2Curt
//
// OUTPUT
// CurtedComplexVector[n-x]           complexvector, Shortened ComplexVector2Curt 
                                     //by x same elements of ComplexVector2compare


IntegerVector Y = match(ComplexVector2Curt,ComplexVector2compare);

  //FoundPositions <- ComplexVector2Curt[Y];
 int n=sum(abs(Y-1)); //length of open positions (FALSE)
 if(n<1){
   ComplexVector Nix;
   return(Nix);
 }
 //ComplexVector OpenPositions  = ComplexVector2Curt[!Y];
 ComplexVector OpenPositions(n);
 for(int i=0;i<n;i++){
   if(Y(i)==0){
     OpenPositions(i)= ComplexVector2Curt(i);
   }
 }
return(OpenPositions);

}

有没有办法解决这个问题? 也许有人知道如何以另一种方式比较 ComplexVectors:目标是找到“ComplexVector2Curt”的不匹配元素。

【问题讨论】:

  • 您在寻找x[!(x %in% y)] 的等价物吗? R API 还提供了一个您可以检查的 match 函数。
  • 是的,我目前正在使用 R 匹配函数:我的代码有一个 for 循环,我想将它移植到 C++,为此我必须在我所在的 C++ 中使用这个函数出现上述错误。
  • 也许它不接受“复杂”(CPLXSXP)作为输入?

标签: c++ r match rcpp


【解决方案1】:

Rcpp::match 依赖于后端IndexHash 模板类,特别是隐式需要IndexHash&lt;&gt;::get_addr 的重载,其中does not exist 用于Rcomplex / CPLXSXP 类型。


一种解决方法是使用std::map 实现此类功能。请注意,这不会像 Rcpp 实现的适当的哈希表解决方案那样有效,但原型化要快得多。首先,一些样板代码:

#include <Rcpp.h>

struct CxLess {
    bool operator()(Rcomplex lhs, Rcomplex rhs) const {
        if (lhs.r < rhs.r) return true;
        if (lhs.i < rhs.i) return true;
        return false;
    }
};

class CxMatch {
private:
    typedef std::map<Rcomplex, int, CxLess> hash_t;
    typedef hash_t::const_iterator const_iterator;
    typedef hash_t::iterator iterator;

    hash_t hash;

    void add_if(Rcomplex key, R_xlen_t value) {
        const_iterator it = hash.find(key);
        if (it == hash.end()) {
            hash[key] = value;
        }
    }

public:
    CxMatch(const Rcpp::ComplexVector& v) {
        R_xlen_t i = 0, sz = v.size();
        for ( ; i < sz; i++) {
            add_if(v[i], i);
        }
    }

    int get_index(Rcomplex key) const {
        const_iterator it = hash.find(key);
        if (it != hash.end()) return it->second;
        return NA_INTEGER;
    }

    Rcpp::IntegerVector apply(Rcpp::ComplexVector x) const {
        R_xlen_t i = 0, sz = x.size();
        Rcpp::IntegerVector res(sz);

        for ( ; i < sz; i++) {
            res[i] = get_index(x[i]);
        }

        return res;
    }
};

CxLess 函子是必需的,因为默认情况下,std::map 将尝试使用 std::less&lt;key_type&gt; 作为比较器,这会导致 Rcomplex 出现编译器错误。使用上述方法,

// [[Rcpp::export]]
Rcpp::ComplexVector cx_setdiff(Rcpp::ComplexVector lhs, Rcpp::ComplexVector rhs) {
    Rcpp::IntegerVector match_pos = CxMatch(rhs).apply(lhs);
    Rcpp::LogicalVector idx = Rcpp::is_na(match_pos);
    return lhs[idx];
} 

运行几个基本测试,这似乎产生了所需的行为:

setdiff(c(1, 3, 5, 7, 11) + 2i, 1:10 + 2i)
#[1] 11+2i

cx_setdiff(c(1, 3, 5, 7, 11) + 2i, 1:10 + 2i)
#[1] 11+2i

setdiff(c(1, 3, 5, 7) + 2i, 1:10 + 2i)
#complex(0)

cx_setdiff(c(1, 3, 5, 7) + 2i, 1:10 + 2i)
#complex(0)

【讨论】:

    【解决方案2】:

    这个怎么样

    // [[Rcpp::export]]
    
    ComplexVector setdiffComplexVectorsC(ComplexVector ComplexVector2Curt,  ComplexVector ComplexVector2compare){
    
    LogicalVector x(ComplexVector2Curt.size());
    
     int i,j;
    
     for(i=0; i < ComplexVector2Curt.size();i++){
    
       for(j=0; j < ComplexVector2compare.size();j++){
    
         if((ComplexVector2Curt[i].i == ComplexVector2compare[j].i) &&
    
            (ComplexVector2Curt[i].r == ComplexVector2compare[j].r))
    
           x[i] = true;
    
       }
    
     }
    
     return(ComplexVector2Curt[!x]);
    
    }
    

    【讨论】:

      【解决方案3】:

      我没有分别评论这两种方法,而是发布一个答案(供未来的读者使用): 我设法找到了一个现实世界的例子,这两种方法都失败了。 很抱歉,我找不到更短的示例: x 和 y 是唯一的。因此,setdiff() 的结果应该是唯一的。方法一 (cx_setdiff) 不会改变 x。方法 2 (setdiffComplexVectorsC) 不是唯一的。与 R 的 setdiff() 相比,这两个结果都不同。

      > length(unique(setdiff(x,y)))
      [1] 46
      > length((setdiff(x,y)))
      [1] 46
      
      > length(unique(setdiffComplexVectorsC(x,y)))
      [1] 41
      length(setdiffComplexVectorsC(x,y))
      [1] 46
      > length(unique(cx_setdiff(x,y)))
      [1] 52
      all(cx_setdiff(x,y)==x)
      [1] TRUE
      
      x=c(16+35i, 16+36i, 16+47i, 16+48i, 17+33i, 17+51i, 18+30i, 18+53i, 
      19+29i, 19+55i, 20+27i, 20+56i, 22+25i, 22+58i, 24+23i, 24+60i, 
      25+23i, 25+61i, 32+19i, 32+64i, 33+19i, 33+65i, 36+18i, 36+65i, 
      38+18i, 38+65i, 40+18i, 40+65i, 42+18i, 42+65i, 45+19i, 45+65i, 
      46+19i, 46+64i, 3+23i, 3+61i, 4+23i, 4+60i, 6+25i, 6+58i, 8+27i, 
      8+56i, 9+29i, 9+55i, 10+30i, 10+53i, 11+33i, 11+51i, 12+35i, 
      12+36i, 12+47i, 12+48i)
      length(unique(x))
      [1] 52
      > length(x)
      [1] 52
      
      y=c(25+76i, 15+39i, 48+31i, 14+13i, 8+70i, 22+34i, 39+31i, 38+66i, 
      30+8i, 50+72i, 46+55i, 21+47i, 45+44i, 38+77i, 1+77i, 22+13i, 
      2+3i, 38+24i, 49+1i, 42+19i, 45+58i, 14+64i, 40+77i, 50+4i, 10+20i, 
      34+76i, 4+79i, 17+26i, 30+41i, 10+30i, 6+20i, 7+65i, 19+13i, 
      13+14i, 6+30i, 25+4i, 32+75i, 26+33i, 3+16i, 41+57i, 17+52i, 
      14+58i, 4+23i, 36+79i, 24+41i, 37+64i, 3+23i, 37+69i, 43+32i, 
      25+63i, 1+34i, 44+68i, 0+0i, 24+44i, 20+70i, 2+17i, 32+78i, 44+8i, 
      9+21i, 38+54i, 2+60i, 27+80i, 16+17i, 13+6i, 23+15i, 33+73i, 
      24+1i, 18+57i, 9+49i, 4+32i, 25+5i, 35+21i, 36+33i, 14+29i, 11+74i, 
      43+48i, 36+44i, 11+61i, 18+3i, 26+2i, 31+71i, 46+73i, 28+1i, 
      28+57i, 23+52i, 25+79i, 10+56i, 50+43i, 25+46i, 32+76i, 6+77i, 
      48+12i, 28+62i, 16+12i, 33+74i, 34+72i, 45+27i, 47+26i, 48+4i, 
      45+68i, 14+59i, 47+2i, 29+69i, 2+46i, 9+34i, 7+36i, 28+28i, 42+44i, 
      33+28i, 9+8i, 18+21i, 43+69i, 46+7i, 2+80i, 33+7i, 15+38i, 48+78i, 
      47+57i, 50+53i, 14+42i, 44+17i, 26+25i, 50+5i, 33+18i, 6+28i, 
      28+2i, 26+55i, 3+56i, 32+28i, 5+69i, 47+31i, 30+28i, 40+43i, 
      41+67i, 2+2i, 36+18i, 26+27i, 10+65i, 37+27i, 32+42i, 37+72i, 
      44+9i, 22+15i, 42+75i, 42+27i, 42+29i, 35+38i, 32+12i, 20+62i, 
      28+52i, 13+58i, 40+22i, 6+3i, 9+75i, 6+55i, 18+73i, 35+32i, 35+59i, 
      32+39i, 28+63i, 18+51i, 22+36i, 29+54i, 23+56i, 19+1i, 5+38i, 
      25+64i, 50+46i, 48+59i, 8+58i, 10+40i, 12+40i, 19+72i, 12+8i, 
      17+50i, 15+30i, 17+6i, 32+73i, 47+11i, 21+5i, 11+63i, 35+42i, 
      31+13i, 33+51i, 29+68i, 9+9i, 13+59i, 44+40i, 20+73i, 21+41i, 
      36+37i, 32+64i, 42+46i, 17+25i, 46+25i, 24+30i, 7+10i, 24+27i, 
      11+73i, 27+27i, 15+12i, 2+9i, 16+36i, 6+61i, 48+20i, 27+15i, 
      14+49i, 40+44i, 35+44i, 30+66i, 46+71i, 38+58i)
      
      length(unique(y))
      [1] 212
      length(y)
      [1] 212
      

      感谢您的尝试。现在我确定,我需要一个自制的实现来解决这个问题。如果我找到上述方法之一的修复程序,我将在此处发布。甚至其他人也可能立即发现问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-06
        • 2016-11-09
        • 1970-01-01
        相关资源
        最近更新 更多