1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
2 //
3 // setdiff.h: Rcpp R/C++ interface class library -- setdiff
4 //
5 // Copyright (C) 2012 - 2014 Dirk Eddelbuettel and Romain Francois
6 //
7 // This file is part of Rcpp.
8 //
9 // Rcpp is free software: you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Rcpp is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
21
22 #ifndef Rcpp__sugar__setdiff_h
23 #define Rcpp__sugar__setdiff_h
24
25 namespace Rcpp{
26 namespace sugar{
27
28 template <typename SET>
29 class RemoveFromSet {
30 public:
RemoveFromSet(SET & set_)31 RemoveFromSet( SET& set_) : set(set_){}
32
33 template <typename T>
operator()34 void operator()(T value){
35 set.erase( value );
36 }
37
38 private:
39 SET& set ;
40 } ;
41
42 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
43 class SetDiff {
44 public:
45 typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
46
SetDiff(const LHS_T & lhs,const RHS_T & rhs)47 SetDiff( const LHS_T& lhs, const RHS_T& rhs) :
48 lhs_set( get_const_begin(lhs), get_const_end(lhs) ),
49 rhs_set( get_const_begin(rhs), get_const_end(rhs) )
50 {
51
52 std::for_each( rhs_set.begin(), rhs_set.end(), RemoveFromSet<SET>(lhs_set) ) ;
53 }
54
get()55 Vector<RTYPE> get() const {
56 R_xlen_t n = lhs_set.size() ;
57 Vector<RTYPE> out = no_init(n) ;
58 std::copy( lhs_set.begin(), lhs_set.end(), out.begin() ) ;
59 return out ;
60 }
61
62 private:
63 typedef RCPP_UNORDERED_SET<STORAGE> SET ;
64 typedef typename SET::const_iterator ITERATOR ;
65 SET lhs_set ;
66 SET rhs_set ;
67
68 } ;
69
70 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
71 class SetEqual {
72 public:
73 typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
74
SetEqual(const LHS_T & lhs,const RHS_T & rhs)75 SetEqual( const LHS_T& lhs, const RHS_T& rhs) :
76 lhs_set( get_const_begin(lhs), get_const_end(lhs) ),
77 rhs_set( get_const_begin(rhs), get_const_end(rhs) )
78 {
79 }
80
get()81 bool get() const {
82 if( lhs_set.size() != rhs_set.size() ) return false ;
83
84 ITERATOR it = lhs_set.begin(), end = lhs_set.end(), rhs_end = rhs_set.end() ;
85 for( ; it != end; ){
86 if( rhs_set.find(*it++) == rhs_end ) return false ;
87 }
88 return true ;
89 }
90
91 private:
92 typedef RCPP_UNORDERED_SET<STORAGE> SET ;
93 typedef typename SET::const_iterator ITERATOR ;
94 SET lhs_set ;
95 SET rhs_set ;
96
97 } ;
98
99 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
100 class Intersect {
101 public:
102 typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
103
Intersect(const LHS_T & lhs,const RHS_T & rhs)104 Intersect( const LHS_T& lhs, const RHS_T& rhs) :
105 intersect()
106 {
107
108 SET lhs_set( get_const_begin(lhs), get_const_end(lhs) ) ;
109 SET rhs_set( get_const_begin(rhs), get_const_end(rhs) ) ;
110
111 ITERATOR end = lhs_set.end() ;
112 ITERATOR rhs_end = rhs_set.end() ;
113 for( ITERATOR it=lhs_set.begin(); it != end; it++){
114 if( rhs_set.find(*it) != rhs_end ) intersect.insert(*it) ;
115 }
116 }
117
get()118 Vector<RTYPE> get() const {
119 R_xlen_t n = intersect.size() ;
120 Vector<RTYPE> out = no_init(n) ;
121 std::copy( intersect.begin(), intersect.end(), out.begin() ) ;
122 return out ;
123 }
124
125 private:
126 typedef RCPP_UNORDERED_SET<STORAGE> SET ;
127 typedef typename SET::const_iterator ITERATOR ;
128 SET intersect ;
129
130 } ;
131
132 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
133 class Union {
134 public:
135 typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
136
Union(const LHS_T & lhs,const RHS_T & rhs)137 Union( const LHS_T& lhs, const RHS_T& rhs) :
138 result( get_const_begin(lhs), get_const_end(lhs) )
139 {
140 result.insert( get_const_begin(rhs), get_const_end(rhs) ) ;
141 }
142
get()143 Vector<RTYPE> get() const {
144 R_xlen_t n = result.size() ;
145 Vector<RTYPE> out = no_init(n) ;
146 std::copy( result.begin(), result.end(), out.begin() ) ;
147 return out ;
148 }
149
150 private:
151 typedef RCPP_UNORDERED_SET<STORAGE> SET ;
152 typedef typename SET::const_iterator ITERATOR ;
153 SET result ;
154
155 } ;
156
157
158 } // sugar
159
160 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
setdiff(const VectorBase<RTYPE,LHS_NA,LHS_T> & lhs,const VectorBase<RTYPE,RHS_NA,RHS_T> & rhs)161 inline Vector<RTYPE> setdiff( const VectorBase<RTYPE,LHS_NA,LHS_T>& lhs, const VectorBase<RTYPE,RHS_NA,RHS_T>& rhs ){
162 return sugar::SetDiff<RTYPE,LHS_NA,LHS_T,RHS_NA,RHS_T>( lhs.get_ref(), rhs.get_ref() ).get() ;
163 }
164
165 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
setequal(const VectorBase<RTYPE,LHS_NA,LHS_T> & lhs,const VectorBase<RTYPE,RHS_NA,RHS_T> & rhs)166 inline bool setequal( const VectorBase<RTYPE,LHS_NA,LHS_T>& lhs, const VectorBase<RTYPE,RHS_NA,RHS_T>& rhs ){
167 return sugar::SetEqual<RTYPE,LHS_NA,LHS_T,RHS_NA,RHS_T>( lhs.get_ref(), rhs.get_ref() ).get() ;
168 }
169
170 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
intersect(const VectorBase<RTYPE,LHS_NA,LHS_T> & lhs,const VectorBase<RTYPE,RHS_NA,RHS_T> & rhs)171 inline Vector<RTYPE> intersect( const VectorBase<RTYPE,LHS_NA,LHS_T>& lhs, const VectorBase<RTYPE,RHS_NA,RHS_T>& rhs ){
172 return sugar::Intersect<RTYPE,LHS_NA,LHS_T,RHS_NA,RHS_T>( lhs.get_ref(), rhs.get_ref() ).get() ;
173 }
174
175 // we cannot use "union" because it is a keyword
176 template <int RTYPE, bool LHS_NA, typename LHS_T, bool RHS_NA, typename RHS_T>
union_(const VectorBase<RTYPE,LHS_NA,LHS_T> & lhs,const VectorBase<RTYPE,RHS_NA,RHS_T> & rhs)177 inline Vector<RTYPE> union_( const VectorBase<RTYPE,LHS_NA,LHS_T>& lhs, const VectorBase<RTYPE,RHS_NA,RHS_T>& rhs ){
178 return sugar::Union<RTYPE,LHS_NA,LHS_T,RHS_NA,RHS_T>( lhs.get_ref(), rhs.get_ref() ).get() ;
179 }
180
181
182
183 } // Rcpp
184 #endif
185
186