Skip to content

Commit e9b0159

Browse files
committed
Use a union for type-punning; enforce 64bit integer
- gcc 4.6.3 was throwing warnings; it seems the recommended way to pun types is with unions as otherwise compiler optimizations can do unexpected things. - use uint64_t rather than unsigned long to enforce 64bit-ness (to match that of double) - We could just use R_IsNaN or R_IsNA, but both are much slower (around 2x faster if I use these unions)
1 parent d68aa72 commit e9b0159

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
2013-12-20 Kevin Ushey <kevinushey@gmail.com>
22

3+
* inst/include/Rcpp/sugar/tools/mapcompare.h: Use a union for
4+
type punning, to avoid compiler warning on aliasing. Also
5+
switch to uint64_t to enforce 64bit comparison.
36
* inst/include/Rcpp/RObject.h: Add missing *this return for
47
RObject_impl::operator=
58

inst/include/Rcpp/sugar/tools/mapcompare.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,28 @@
2222
#ifndef Rcpp__sugar__tools__mapcompare_h
2323
#define Rcpp__sugar__tools__mapcompare_h
2424

25+
#include <cstdint>
26+
using std::uint64_t;
27+
2528
namespace Rcpp {
2629
namespace sugar {
2730

28-
static unsigned long const R_UNSIGNED_LONG_NA_REAL = *(unsigned long*)(&NA_REAL);
29-
static unsigned long const R_UNSIGNED_LONG_NAN_REAL = *(unsigned long*)(&R_NaN);
31+
union DoublePunner {
32+
double d;
33+
uint64_t p;
34+
};
35+
36+
static const DoublePunner NA_REAL_PUN = { NA_REAL };
37+
static const DoublePunner NAN_REAL_PUN = { R_NaN };
3038

3139
inline bool Rcpp_IsNA(double x) {
32-
return *reinterpret_cast<unsigned long*>(&x) == R_UNSIGNED_LONG_NA_REAL;
40+
DoublePunner xp = { x };
41+
return xp.p == NA_REAL_PUN.p;
3342
}
3443

3544
inline bool Rcpp_IsNaN(double x) {
36-
return *reinterpret_cast<unsigned long*>(&x) == R_UNSIGNED_LONG_NAN_REAL;
45+
DoublePunner xp = { x };
46+
return xp.p == NAN_REAL_PUN.p;
3747
}
3848

3949
inline int StrCmp(SEXP x, SEXP y) {

0 commit comments

Comments
 (0)