Skip to content

Commit 8754a85

Browse files
committed
Some VisualStudio compatibility hacks.
1 parent 392def8 commit 8754a85

File tree

2 files changed

+173
-20
lines changed

2 files changed

+173
-20
lines changed

include/util.h

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,80 @@
11
#ifndef FRAMEOFREFERENCE_INCLUDE_UTIL_H
22
#define FRAMEOFREFERENCE_INCLUDE_UTIL_H
3-
#include <iso646.h> // mostly for Microsoft compilers
3+
#include <iso646.h> // mostly for Microsoft
4+
#ifdef _MSC_VER
5+
/* Microsoft C/C++-compatible compiler */
6+
#include <intrin.h>
7+
8+
#ifndef __clang__ // if one compiles with MSVC *with* clang, then these intrinsics are defined!!!
9+
// sadly there is no way to check whether we are missing these intrinsics specifically.
10+
11+
/* wrappers for Visual Studio built-ins that look like gcc built-ins */
12+
/* result might be undefined when input_num is zero */
13+
static inline int __builtin_ctzll(unsigned long long input_num) {
14+
unsigned long index;
15+
#ifdef _WIN64 // highly recommended!!!
16+
_BitScanForward64(&index, input_num);
17+
#else // if we must support 32-bit Windows
18+
if ((uint32_t)input_num != 0) {
19+
_BitScanForward(&index, (uint32_t)input_num);
20+
}
21+
else {
22+
_BitScanForward(&index, (uint32_t)(input_num >> 32));
23+
index += 32;
24+
}
25+
#endif
26+
return index;
27+
}
28+
29+
/* result might be undefined when input_num is zero */
30+
static inline int __builtin_clzll(unsigned long long input_num) {
31+
unsigned long index;
32+
#ifdef _WIN64 // highly recommended!!!
33+
_BitScanReverse64(&index, input_num);
34+
#else // if we must support 32-bit Windows
35+
if (input_num > 0xFFFFFFF) {
36+
_BitScanReverse(&index, (uint32_t)(input_num >> 32));
37+
}
38+
else {
39+
_BitScanReverse(&index, (uint32_t)(input_num));
40+
index += 32;
41+
}
42+
#endif
43+
return 63 - index;
44+
}
45+
46+
/* result might be undefined when input_num is zero */
47+
static inline int __builtin_clz(int input_num) {
48+
unsigned long index;
49+
_BitScanReverse(&index, input_num);
50+
return 31 - index;
51+
}
52+
53+
/* result might be undefined when input_num is zero */
54+
static inline int __builtin_popcountll(unsigned long long input_num) {
55+
#ifdef _WIN64 // highly recommended!!!
56+
return (int)__popcnt64(input_num);
57+
#else // if we must support 32-bit Windows
58+
return (int)(__popcnt((uint32_t)input_num) + __popcnt((uint32_t)(input_num >> 32)));
59+
#endif
60+
}
61+
62+
static inline void __builtin_unreachable() {
63+
__assume(0);
64+
}
65+
#endif
66+
#endif
67+
68+
469
#include <stdint.h> // part of Visual Studio 2010 and better
570

671
// integer logarithm function
772
static inline uint32_t bits(const uint32_t v) {
873
return v == 0 ? 0 : 32 - __builtin_clz(v); // todo: make portable (Visual studio)
974
}
1075

76+
77+
1178
// integer logarithm function
1279
static inline uint32_t bits64(const uint64_t v) {
1380
return v == 0 ? 0 : 64 - __builtin_clzll(v); // todo: make portable (Visual studio)

src/test.cpp

Lines changed: 105 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
* Apache License Version 2.0 http://www.apache.org/licenses/.
55
* (c) Daniel Lemire 2013
66
*/
7-
7+
#include <chrono>
88
#include <sys/stat.h>
9-
#include <sys/time.h>
109
#include <sys/types.h>
1110
#ifdef _OPENMP
1211
#include <omp.h>
@@ -20,29 +19,116 @@
2019

2120
using namespace std;
2221

22+
23+
//
24+
// VS2012 bug: high_precision_clock is defined as system_clock and precision is
25+
// about 15 MS!!
26+
// See: https://connect.microsoft.com/VisualStudio/feedback/details/719443
27+
//
28+
// Implementation has been taken from a post on stackoverflow and adapted here
29+
// http://stackoverflow.com/questions/13263277/difference-between-stdsystem-clock-and-stdsteady-clock
30+
//
31+
#ifdef _WIN32
32+
#define NOMINMAX
33+
#define WINDOWS_LEAN_AND_MEAN
34+
#include <windows.h>
35+
36+
struct qpc_clock {
37+
typedef std::chrono::nanoseconds duration;
38+
typedef duration::rep rep;
39+
typedef duration::period period;
40+
typedef std::chrono::time_point<qpc_clock, duration> time_point;
41+
static time_point now() {
42+
static bool isInited = false;
43+
static LARGE_INTEGER frequency = { 0, 0 };
44+
if (!isInited) {
45+
if (QueryPerformanceFrequency(&frequency) == 0) {
46+
throw std::logic_error("QueryPerformanceCounter not supported: " +
47+
std::to_string(GetLastError()));
48+
}
49+
isInited = true;
50+
}
51+
LARGE_INTEGER counter;
52+
QueryPerformanceCounter(&counter);
53+
return time_point(duration(static_cast<rep>((double)counter.QuadPart /
54+
frequency.QuadPart *
55+
period::den / period::num)));
56+
}
57+
};
58+
59+
#endif
60+
61+
/**
62+
* author: Preston Bannister
63+
*/
2364
class WallClockTimer {
2465
public:
25-
struct timeval t1, t2;
66+
#ifdef _WIN32
67+
typedef qpc_clock clock;
68+
#else
69+
typedef std::chrono::high_resolution_clock clock;
70+
#endif
2671

72+
std::chrono::time_point<clock> t1, t2;
73+
WallClockTimer() : t1(), t2() {
74+
t1 = clock::now();
75+
t2 = t1;
76+
}
77+
void reset() {
78+
t1 = clock::now();
79+
t2 = t1;
80+
}
81+
uint64_t elapsed() {
82+
std::chrono::microseconds delta =
83+
std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
84+
return delta.count();
85+
}
86+
uint64_t split() {
87+
t2 = clock::now();
88+
return elapsed();
89+
}
90+
};
91+
92+
#ifndef _WIN32
93+
94+
class CPUTimer {
2795
public:
28-
WallClockTimer() : t1(), t2() {
29-
gettimeofday(&t1, 0);
30-
t2 = t1;
31-
}
32-
void reset() {
33-
gettimeofday(&t1, 0);
34-
t2 = t1;
35-
}
36-
int elapsed() {
37-
return ((t2.tv_sec - t1.tv_sec) * 1000) +
38-
((t2.tv_usec - t1.tv_usec) / 1000);
39-
}
40-
int split() {
41-
gettimeofday(&t2, 0);
42-
return elapsed();
43-
}
96+
// clock_t t1, t2;
97+
struct rusage t1, t2;
98+
99+
CPUTimer() : t1(), t2() {
100+
getrusage(RUSAGE_SELF, &t1);
101+
// t1 = clock();
102+
t2 = t1;
103+
}
104+
void reset() {
105+
getrusage(RUSAGE_SELF, &t1);
106+
t2 = t1;
107+
}
108+
// proxy for userelapsed
109+
uint64_t elapsed() { return totalelapsed(); }
110+
111+
uint64_t totalelapsed() { return userelapsed() + systemelapsed(); }
112+
// returns the *user* CPU time in micro seconds (mu s)
113+
uint64_t userelapsed() {
114+
return ((t2.ru_utime.tv_sec - t1.ru_utime.tv_sec) * 1000ULL * 1000ULL) +
115+
((t2.ru_utime.tv_usec - t1.ru_utime.tv_usec));
116+
}
117+
118+
// returns the *system* CPU time in micro seconds (mu s)
119+
uint64_t systemelapsed() {
120+
return ((t2.ru_stime.tv_sec - t1.ru_stime.tv_sec) * 1000ULL * 1000ULL) +
121+
((t2.ru_stime.tv_usec - t1.ru_stime.tv_usec));
122+
}
123+
124+
uint64_t split() {
125+
getrusage(RUSAGE_SELF, &t2);
126+
return elapsed();
127+
}
44128
};
45129

130+
#endif
131+
46132
void displayUsage() { cout << "run as test nameoffile" << endl; }
47133

48134
vector<uint32_t> loadVector(string filename) {

0 commit comments

Comments
 (0)