Skip to content

Commit a5b1d88

Browse files
committed
Some reformatting, + a NEWS entry
1 parent 9d4878c commit a5b1d88

File tree

7 files changed

+116
-107
lines changed

7 files changed

+116
-107
lines changed

inst/NEWS.Rd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
objects
1212
\item Add missing default constructor to Reference class that was
1313
omitted in the header-only rewrite
14+
\item Fixes re: the NA, NaN handling for the IndexHash class, as well
15+
as the vector .sort() method. These fixes ensure that sugar functions
16+
depending on IndexHash (unique, sort_unique, match) will now properly
17+
handle NA and NaN values for numeric vectors.
1418
}
1519
}
1620
}

inst/include/Rcpp/hash/IndexHash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//
66
// Copyright (C) 2010, 2011 Simon Urbanek
77
// Copyright (C) 2012 Dirk Eddelbuettel and Romain Francois
8+
// Copyright (C) 2014 Dirk Eddelbuettel, Romain Francois and Kevin Ushey
89
//
910
// This file is part of Rcpp.
1011
//

inst/include/Rcpp/internal/NAComparator.h

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,54 +28,55 @@ namespace Rcpp{
2828
namespace internal {
2929

3030
inline int StrCmp(SEXP x, SEXP y) {
31-
if (x == NA_STRING) return (y == NA_STRING ? 0 : 1);
32-
if (y == NA_STRING) return -1;
33-
if (x == y) return 0; // same string in cache
34-
return strcmp(char_nocheck(x), char_nocheck(y));
31+
if (x == NA_STRING) return (y == NA_STRING ? 0 : 1);
32+
if (y == NA_STRING) return -1;
33+
if (x == y) return 0; // same string in cache
34+
return strcmp(char_nocheck(x), char_nocheck(y));
3535
}
3636

3737
template <typename T>
3838
struct NAComparator {
39-
inline bool operator()(T left, T right) const {
40-
return left < right;
41-
}
39+
inline bool operator()(T left, T right) const {
40+
return left < right;
41+
}
4242
};
4343

4444
template <>
4545
struct NAComparator<int> {
46-
inline bool operator()(int left, int right) const {
47-
if (left == NA_INTEGER) return false;
48-
if (right == NA_INTEGER) return true;
49-
return left < right;
50-
}
46+
inline bool operator()(int left, int right) const {
47+
if (left == NA_INTEGER) return false;
48+
if (right == NA_INTEGER) return true;
49+
return left < right;
50+
}
5151
};
5252

5353
template <>
5454
struct NAComparator<double> {
55-
inline bool operator()(double left, double right) const {
55+
inline bool operator()(double left, double right) const {
5656

57-
bool leftNaN = (left != left);
58-
bool rightNaN = (right != right);
59-
60-
// this branch inspired by data.table: see
61-
// https://github.com/arunsrinivasan/datatable/commit/1a3e476d3f746e18261662f484d2afa84ac7a146#commitcomment-4885242
62-
if (Rcpp_IsNaN(right) and Rcpp_IsNA(left)) return true;
57+
bool leftNaN = (left != left);
58+
bool rightNaN = (right != right);
59+
60+
// this branch inspired by data.table: see
61+
// https://github.com/arunsrinivasan/datatable/commit/1a3e476d3f746e18261662f484d2afa84ac7a146#commitcomment-4885242
62+
if (Rcpp_IsNaN(right) and Rcpp_IsNA(left))
63+
return true;
64+
65+
if (leftNaN != rightNaN) {
66+
return leftNaN < rightNaN;
67+
} else {
68+
return left < right;
69+
}
6370

64-
if (leftNaN != rightNaN) {
65-
return leftNaN < rightNaN;
66-
} else {
67-
return left < right;
68-
}
69-
70-
}
71+
}
7172

7273
};
7374

7475
template <>
7576
struct NAComparator<SEXP> {
76-
inline bool operator()(SEXP left, SEXP right) const {
77-
return StrCmp(left, right) < 0;
78-
}
77+
inline bool operator()(SEXP left, SEXP right) const {
78+
return StrCmp(left, right) < 0;
79+
}
7980
};
8081

8182
}

inst/include/Rcpp/internal/NAEquals.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ namespace internal {
2626

2727
template <typename T>
2828
struct NAEquals {
29-
inline bool operator()(T left, T right) const {
30-
return left == right;
31-
}
29+
inline bool operator()(T left, T right) const {
30+
return left == right;
31+
}
3232
};
3333

3434
// TODO: check different kinds of NA, NaNs
3535
template <>
3636
struct NAEquals<double> {
37-
inline bool operator()(double left, double right) const {
38-
return memcmp(&left, &right, sizeof(double)) == 0;
39-
}
37+
inline bool operator()(double left, double right) const {
38+
return memcmp(&left, &right, sizeof(double)) == 0;
39+
}
4040
};
4141

4242
}

inst/include/Rcpp/internal/na.h

Lines changed: 65 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -21,77 +21,80 @@
2121
// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
2222

2323
namespace Rcpp {
24-
namespace internal {
24+
namespace internal {
2525

26-
// On 64bit processors, NAs can change
27-
// we can still get a performance benefit by checking for specific
28-
// bit patterns, though
29-
30-
// we rely on the presence of unsigned long long types (could do it with
31-
// a union, but that's messier; this is cleaner)
32-
#ifdef RCPP_HAS_LONG_LONG_TYPES
33-
34-
#ifdef HAS_STATIC_ASSERT
35-
static_assert(
36-
sizeof(rcpp_ulong_long_type) == sizeof(double),
37-
"unsigned long long and double have same size"
38-
);
39-
#endif
40-
41-
static const rcpp_ulong_long_type SmallNA = 0x7FF00000000007A2;
42-
static const rcpp_ulong_long_type LargeNA = 0x7FF80000000007A2;
43-
44-
struct NACanChange {
45-
enum { value = sizeof(void*) == 8 };
46-
};
47-
48-
template <bool NACanChange>
49-
bool Rcpp_IsNA__impl(double);
50-
51-
template <>
52-
inline bool Rcpp_IsNA__impl<true>(double x) {
53-
return memcmp(
26+
// On 64bit processors, NAs can change
27+
// we can still get a performance benefit by checking for specific
28+
// bit patterns, though
29+
30+
// we rely on the presence of unsigned long long types (could do it with
31+
// a union, but that's messier; this is cleaner)
32+
#ifdef RCPP_HAS_LONG_LONG_TYPES
33+
34+
#ifdef HAS_STATIC_ASSERT
35+
static_assert(
36+
sizeof(rcpp_ulong_long_type) == sizeof(double),
37+
"unsigned long long and double have same size"
38+
);
39+
#endif
40+
41+
// motivation: on 32bit architectures, we only see 'LargeNA'
42+
// as defined ashead; on 64bit architectures, R defaults to
43+
// 'SmallNA' for R_NaReal, but this can get promoted to 'LargeNA'
44+
// if a certain operation can create a 'signalling' NA.
45+
static const rcpp_ulong_long_type SmallNA = 0x7FF00000000007A2;
46+
static const rcpp_ulong_long_type LargeNA = 0x7FF80000000007A2;
47+
48+
struct NACanChange {
49+
enum { value = sizeof(void*) == 8 };
50+
};
51+
52+
template <bool NACanChange>
53+
bool Rcpp_IsNA__impl(double);
54+
55+
template <>
56+
inline bool Rcpp_IsNA__impl<true>(double x) {
57+
return memcmp(
5458
(void*) &x,
5559
(void*) &SmallNA,
5660
sizeof(double)
57-
) == 0 or memcmp(
61+
) == 0 or memcmp(
5862
(void*) &x,
5963
(void*) &LargeNA,
6064
sizeof(double)
61-
) == 0;
62-
}
63-
64-
template <>
65-
inline bool Rcpp_IsNA__impl<false>(double x) {
66-
printf("false\n");
67-
return memcmp(
65+
) == 0;
66+
}
67+
68+
template <>
69+
inline bool Rcpp_IsNA__impl<false>(double x) {
70+
return memcmp(
6871
(void*) &x,
6972
(void*) &LargeNA,
7073
sizeof(double)
71-
) == 0;
72-
}
73-
74-
inline bool Rcpp_IsNA(double x) {
75-
return Rcpp_IsNA__impl< NACanChange::value >(x);
76-
}
77-
78-
inline bool Rcpp_IsNaN(double x) {
79-
return R_IsNaN(x);
80-
}
81-
82-
#else
83-
84-
// fallback when we don't have unsigned long long
85-
86-
inline bool Rcpp_IsNA(double x) {
87-
return R_IsNA(x);
88-
}
89-
90-
inline bool Rcpp_IsNaN(double x) {
91-
return R_IsNaN(x);
92-
}
93-
94-
#endif
74+
) == 0;
75+
}
76+
77+
inline bool Rcpp_IsNA(double x) {
78+
return Rcpp_IsNA__impl< NACanChange::value >(x);
79+
}
80+
81+
inline bool Rcpp_IsNaN(double x) {
82+
return R_IsNaN(x);
83+
}
84+
85+
#else
86+
87+
// fallback when we don't have unsigned long long
88+
89+
inline bool Rcpp_IsNA(double x) {
90+
return R_IsNA(x);
91+
}
92+
93+
inline bool Rcpp_IsNaN(double x) {
94+
return R_IsNaN(x);
95+
}
96+
97+
#endif
9598

96-
}
99+
}
97100
}

inst/unitTests/cpp/na.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,21 @@ using namespace Rcpp ;
2424

2525
// [[Rcpp::export]]
2626
bool Rcpp_IsNA(double x) {
27-
return internal::Rcpp_IsNA(x);
27+
return internal::Rcpp_IsNA(x);
2828
}
2929

3030
// [[Rcpp::export]]
3131
bool Rcpp_IsNaN(double x) {
32-
return internal::Rcpp_IsNaN(x);
32+
return internal::Rcpp_IsNaN(x);
3333
}
3434

3535
// [[Rcpp::export]]
3636
bool R_IsNA_(double x) {
37-
return ::R_IsNA(x);
37+
return ::R_IsNA(x);
3838
}
3939

4040
// [[Rcpp::export]]
4141
bool R_IsNaN_(double x) {
42-
return ::R_IsNaN(x);
42+
return ::R_IsNaN(x);
4343
}
4444

inst/unitTests/runit.na.R

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@
2121
.runThisTest <- Sys.getenv("RunAllRcppTests") == "yes"
2222

2323
if (.runThisTest) {
24-
25-
.setUp <- Rcpp:::unitTestSetup("na.cpp")
26-
27-
test.na <- function() {
24+
25+
.setUp <- Rcpp:::unitTestSetup("na.cpp")
26+
27+
test.na <- function() {
2828
checkIdentical( R_IsNA_(NA_real_), Rcpp_IsNA(NA_real_) )
2929
checkIdentical( R_IsNA_(NA_real_+1), Rcpp_IsNA(NA_real_+1) )
3030
checkIdentical( R_IsNA_(NA_real_+NaN), Rcpp_IsNA(NA_real_+NaN) )
3131
checkIdentical( R_IsNA_(NaN+NA_real_), Rcpp_IsNA(NaN+NA_real_) )
3232
checkIdentical( R_IsNaN_(NA_real_), Rcpp_IsNaN(NA_real_) )
3333
checkIdentical( R_IsNaN_(NaN), Rcpp_IsNaN(NaN) )
3434
checkIdentical( R_IsNaN_(NaN+1), Rcpp_IsNaN(NaN+1) )
35-
}
36-
35+
}
36+
3737
}

0 commit comments

Comments
 (0)