Skip to content

Commit 6cf57a8

Browse files
committed
add MapCompare + #defines so map works when using std::map
1 parent 80d0b45 commit 6cf57a8

File tree

2 files changed

+106
-3
lines changed

2 files changed

+106
-3
lines changed

inst/include/Rcpp/sugar/functions/table.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,25 @@
2121

2222
#ifndef Rcpp__sugar__table_h
2323
#define Rcpp__sugar__table_h
24+
25+
#ifdef RCPP_USING_MAP
26+
#include <Rcpp/sugar/tools/mapcompare.h>
27+
#endif
2428

2529
namespace Rcpp{
2630
namespace sugar{
2731

2832
template <typename HASH, typename STORAGE>
2933
class CountInserter {
3034
public:
31-
CountInserter( HASH& hash_ ) : hash(hash_), index(0) {}
35+
CountInserter( HASH& hash_ ) : hash(hash_) {}
3236

3337
inline void operator()( STORAGE value ){
3438
hash[value]++ ;
3539
}
3640

3741
private:
3842
HASH& hash ;
39-
int index;
4043
} ;
4144

4245
template <typename HASH, int RTYPE>
@@ -63,9 +66,11 @@ class Table {
6366

6467
Table( const TABLE_T& table ): hash(), map() {
6568
// populate the initial hash
69+
Rprintf("populating hash\n");
6670
std::for_each( table.begin(), table.end(), Inserter(hash) ) ;
6771

6872
// populate the map, sorted by keys
73+
Rprintf("populating map\n");
6974
map.insert( hash.begin(), hash.end() ) ;
7075
}
7176

@@ -80,7 +85,13 @@ class Table {
8085
}
8186

8287
private:
83-
typedef RCPP_UNORDERED_MAP<STORAGE, int> HASH ;
88+
// bugfix for standard map
89+
#ifdef RCPP_USING_MAP
90+
typedef RCPP_UNORDERED_MAP<STORAGE, int, MapCompare<STORAGE> >HASH ;
91+
#else
92+
typedef RCPP_UNORDERED_MAP<STORAGE, int> HASH ;
93+
#endif
94+
8495
typedef CountInserter<HASH,STORAGE> Inserter ;
8596

8697
typedef std::map<STORAGE, int, typename Rcpp::traits::comparator_type<RTYPE>::type > SORTED_MAP ;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
2+
//
3+
// table.h: Rcpp R/C++ interface class library -- table match
4+
//
5+
// Copyright (C) 2012 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__tools__mapcompare_h
23+
#define Rcpp__sugar__tools__mapcompare_h
24+
25+
#define R_UNSIGNED_LONG_NAN_REAL 0x7ff8000000000000
26+
27+
namespace Rcpp {
28+
namespace sugar {
29+
30+
inline bool Rcpp_IsNA(double x) {
31+
return *reinterpret_cast<unsigned long*>(&x) == *reinterpret_cast<unsigned long*>(&NA_REAL);
32+
}
33+
34+
inline bool Rcpp_IsNaN(double x) {
35+
return *reinterpret_cast<unsigned long*>(&x) == R_UNSIGNED_LONG_NAN_REAL;
36+
}
37+
38+
inline int StrCmp(SEXP x, SEXP y) {
39+
if (x == NA_STRING) return (y == NA_STRING ? 0 : 1);
40+
if (y == NA_STRING) return -1;
41+
if (x == y) return 0; // same string in cache
42+
return strcmp(CHAR(x), CHAR(y));
43+
}
44+
45+
template <typename T>
46+
struct MapCompare {
47+
inline bool operator()(T left, T right) const {
48+
return left < right;
49+
}
50+
};
51+
52+
template <>
53+
struct MapCompare<int> {
54+
inline bool operator()(int left, int right) const {
55+
if (left == NA_INTEGER) return false;
56+
if (right == NA_INTEGER) return true;
57+
return left < right;
58+
}
59+
};
60+
61+
template <>
62+
struct MapCompare<double> {
63+
inline bool operator()(double left, double right) const {
64+
65+
bool leftNaN = (left != left);
66+
bool rightNaN = (right != right);
67+
68+
// this branch inspired by data.table: see
69+
// https://github.com/arunsrinivasan/datatable/commit/1a3e476d3f746e18261662f484d2afa84ac7a146#commitcomment-4885242
70+
if (Rcpp_IsNaN(right) and Rcpp_IsNA(left)) return true;
71+
72+
if (leftNaN != rightNaN) {
73+
return leftNaN < rightNaN;
74+
} else {
75+
return left < right;
76+
}
77+
78+
}
79+
80+
};
81+
82+
template <>
83+
struct MapCompare<SEXP> {
84+
inline bool operator()(SEXP left, SEXP right) const {
85+
return StrCmp(left, right) < 0;
86+
}
87+
};
88+
89+
}
90+
}
91+
92+
#endif

0 commit comments

Comments
 (0)