Skip to content

Commit

Permalink
Join visitors handle Date objects with heterogenous repretation (in…
Browse files Browse the repository at this point in the history
…teger

  and numeric), making e.g `all.equal` more resistant. closes #1204.
  • Loading branch information
romainfrancois committed Aug 14, 2015
1 parent 8ca840c commit 0634931
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 89 deletions.
5 changes: 4 additions & 1 deletion NEWS.md
Expand Up @@ -60,7 +60,10 @@

* joins handle matrix columns better (#1230).

* strings ordering more resistant to collate issues (#1315).
* strings ordering more resistant to collate issues (#1315).

* Join visitors handle `Date` objects with heterogenous repretation (integer
and numeric), making e.g `all.equal` more resistant (#1204).

# dplyr 0.4.2

Expand Down
103 changes: 101 additions & 2 deletions inst/include/dplyr/JoinVisitorImpl.h
Expand Up @@ -445,7 +445,6 @@ namespace dplyr{

private:
inline SEXP promote( Vec vec){
// vec.attr( "class" ) = JoinVisitorImpl::left.attr( "class" );
copy_most_attributes(vec,JoinVisitorImpl::left ) ;
return vec ;
}
Expand All @@ -458,10 +457,110 @@ namespace dplyr{
__CLASS__( const NumericVector& left_, const NumericVector& right_) : \
Parent(left_, right_){} \
} ;
PROMOTE_JOIN_VISITOR(DateJoinVisitor)
PROMOTE_JOIN_VISITOR(POSIXctJoinVisitor)

JoinVisitor* join_visitor( SEXP, SEXP, const std::string&, const std::string&, bool warn ) ;

class DateJoinVisitorGetter {
public:
virtual ~DateJoinVisitorGetter(){} ;
virtual double get(int i) = 0 ;
} ;

template <int RTYPE>
class DateJoinVisitorGetterImpl : public DateJoinVisitorGetter {
public:
DateJoinVisitorGetterImpl( SEXP x) : data(x){}

inline double get(int i){
return (double) data[i] ;
}

private:
Vector<RTYPE> data ;
} ;

class DateJoinVisitor : public JoinVisitor, public comparisons<REALSXP>{
public:
typedef comparisons<REALSXP> Compare ;
typedef boost::hash<double> hasher ;

DateJoinVisitor( SEXP lhs, SEXP rhs)
{
if( TYPEOF(lhs) == INTSXP ) {
left = new DateJoinVisitorGetterImpl<INTSXP>(lhs) ;
} else if( TYPEOF(lhs) == REALSXP) {
left = new DateJoinVisitorGetterImpl<REALSXP>(lhs) ;
} else {
stop("Date objects should be represented as integer or numeric") ;
}

if( TYPEOF(rhs) == INTSXP) {
right = new DateJoinVisitorGetterImpl<INTSXP>(rhs) ;
} else if( TYPEOF(rhs) == REALSXP) {
right = new DateJoinVisitorGetterImpl<REALSXP>(rhs) ;
} else {
stop("Date objects should be represented as integer or numeric") ;
}

}

~DateJoinVisitor(){
delete left ;
delete right;
}

inline size_t hash(int i) {
return hash_fun( get(i) ) ;
}
inline bool equal(int i, int j) {
return Compare::equal_or_both_na(
get(i), get(j)
) ;
}

inline SEXP subset( const std::vector<int>& indices ) {
int n = indices.size() ;
NumericVector res = no_init(n) ;
for( int i=0; i<n; i++) {
res[i] = get(indices[i]) ;
}
res.attr("class") = "Date" ;
return res ;
}

inline SEXP subset( const VisitorSetIndexSet<DataFrameJoinVisitors>& set ) {
int n = set.size() ;
NumericVector res = no_init(n) ;
VisitorSetIndexSet<DataFrameJoinVisitors>::const_iterator it=set.begin() ;
for( int i=0; i<n; i++, ++it) {
res[i] = get(*it) ;
}
res.attr("class") = "Date" ;
return res ;
}

inline void print(int i){
Rcpp::Rcout << get(i) << std::endl ;
}

private:
DateJoinVisitorGetter* left ;
DateJoinVisitorGetter* right ;
hasher hash_fun ;

DateJoinVisitor( const DateJoinVisitor& ) ;

inline double get( int i) {
if( i>= 0 ){
return left->get(i) ;
} else {
return right->get(-i-1) ;
}
}
} ;


}

#endif

0 comments on commit 0634931

Please sign in to comment.