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