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