sparsam 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+ #if !defined(spp_memory_h_guard)
2
+ #define spp_memory_h_guard
3
+
4
+ #include <cstdint>
5
+ #include <cstring>
6
+ #include <cstdlib>
7
+
8
+ #if defined(_WIN32) || defined( __CYGWIN__)
9
+ #define SPP_WIN
10
+ #endif
11
+
12
+ #ifdef SPP_WIN
13
+ #include <windows.h>
14
+ #include <Psapi.h>
15
+ #undef min
16
+ #undef max
17
+ #else
18
+ #include <sys/types.h>
19
+ #include <sys/sysinfo.h>
20
+ #endif
21
+
22
+ namespace spp
23
+ {
24
+ uint64_t GetSystemMemory()
25
+ {
26
+ #ifdef SPP_WIN
27
+ MEMORYSTATUSEX memInfo;
28
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
29
+ GlobalMemoryStatusEx(&memInfo);
30
+ return static_cast<uint64_t>(memInfo.ullTotalPageFile);
31
+ #else
32
+ struct sysinfo memInfo;
33
+ sysinfo (&memInfo);
34
+ auto totalVirtualMem = memInfo.totalram;
35
+
36
+ totalVirtualMem += memInfo.totalswap;
37
+ totalVirtualMem *= memInfo.mem_unit;
38
+ return static_cast<uint64_t>(totalVirtualMem);
39
+ #endif
40
+ }
41
+
42
+ uint64_t GetTotalMemoryUsed()
43
+ {
44
+ #ifdef SPP_WIN
45
+ MEMORYSTATUSEX memInfo;
46
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
47
+ GlobalMemoryStatusEx(&memInfo);
48
+ return static_cast<uint64_t>(memInfo.ullTotalPageFile - memInfo.ullAvailPageFile);
49
+ #else
50
+ struct sysinfo memInfo;
51
+ sysinfo(&memInfo);
52
+ auto virtualMemUsed = memInfo.totalram - memInfo.freeram;
53
+
54
+ virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
55
+ virtualMemUsed *= memInfo.mem_unit;
56
+
57
+ return static_cast<uint64_t>(virtualMemUsed);
58
+ #endif
59
+ }
60
+
61
+ uint64_t GetProcessMemoryUsed()
62
+ {
63
+ #ifdef SPP_WIN
64
+ PROCESS_MEMORY_COUNTERS_EX pmc;
65
+ GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pmc), sizeof(pmc));
66
+ return static_cast<uint64_t>(pmc.PrivateUsage);
67
+ #else
68
+ auto parseLine =
69
+ [](char* line)->int
70
+ {
71
+ auto i = strlen(line);
72
+
73
+ while(*line < '0' || *line > '9')
74
+ {
75
+ line++;
76
+ }
77
+
78
+ line[i-3] = '\0';
79
+ i = atoi(line);
80
+ return i;
81
+ };
82
+
83
+ auto file = fopen("/proc/self/status", "r");
84
+ auto result = -1;
85
+ char line[128];
86
+
87
+ while(fgets(line, 128, file) != nullptr)
88
+ {
89
+ if(strncmp(line, "VmSize:", 7) == 0)
90
+ {
91
+ result = parseLine(line);
92
+ break;
93
+ }
94
+ }
95
+
96
+ fclose(file);
97
+ return static_cast<uint64_t>(result) * 1024;
98
+ #endif
99
+ }
100
+
101
+ uint64_t GetPhysicalMemory()
102
+ {
103
+ #ifdef SPP_WIN
104
+ MEMORYSTATUSEX memInfo;
105
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
106
+ GlobalMemoryStatusEx(&memInfo);
107
+ return static_cast<uint64_t>(memInfo.ullTotalPhys);
108
+ #else
109
+ struct sysinfo memInfo;
110
+ sysinfo(&memInfo);
111
+
112
+ auto totalPhysMem = memInfo.totalram;
113
+
114
+ totalPhysMem *= memInfo.mem_unit;
115
+ return static_cast<uint64_t>(totalPhysMem);
116
+ #endif
117
+ }
118
+
119
+ }
120
+
121
+ #endif // spp_memory_h_guard
@@ -0,0 +1,76 @@
1
+ #if !defined(spp_smartptr_h_guard)
2
+ #define spp_smartptr_h_guard
3
+
4
+
5
+ /* -----------------------------------------------------------------------------------------------
6
+ * quick version of intrusive_ptr
7
+ * -----------------------------------------------------------------------------------------------
8
+ */
9
+
10
+ #include <cassert>
11
+ #include <sparsepp/spp_config.h>
12
+
13
+ // ------------------------------------------------------------------------
14
+ class spp_rc
15
+ {
16
+ public:
17
+ spp_rc() : _cnt(0) {}
18
+ spp_rc(const spp_rc &) : _cnt(0) {}
19
+ void increment() const { ++_cnt; }
20
+ void decrement() const { assert(_cnt); if (--_cnt == 0) delete this; }
21
+ unsigned count() const { return _cnt; }
22
+
23
+ protected:
24
+ virtual ~spp_rc() {}
25
+
26
+ private:
27
+ mutable unsigned _cnt;
28
+ };
29
+
30
+ // ------------------------------------------------------------------------
31
+ template <class T>
32
+ class spp_sptr
33
+ {
34
+ public:
35
+ spp_sptr() : _p(0) {}
36
+ spp_sptr(T *p) : _p(p) { if (_p) _p->increment(); }
37
+ spp_sptr(const spp_sptr &o) : _p(o._p) { if (_p) _p->increment(); }
38
+ #ifndef SPP_NO_CXX11_RVALUE_REFERENCES
39
+ spp_sptr(spp_sptr &&o) : _p(o._p) { o._p = (T *)0; }
40
+ spp_sptr& operator=(spp_sptr &&o)
41
+ {
42
+ if (_p) _p->decrement();
43
+ _p = o._p;
44
+ o._p = (T *)0;
45
+ }
46
+ #endif
47
+ ~spp_sptr() { if (_p) _p->decrement(); }
48
+ spp_sptr& operator=(const spp_sptr &o) { reset(o._p); return *this; }
49
+ T* get() const { return _p; }
50
+ void swap(spp_sptr &o) { T *tmp = _p; _p = o._p; o._p = tmp; }
51
+ void reset(const T *p = 0)
52
+ {
53
+ if (p == _p)
54
+ return;
55
+ if (_p) _p->decrement();
56
+ _p = (T *)p;
57
+ if (_p) _p->increment();
58
+ }
59
+ T* operator->() const { return const_cast<T *>(_p); }
60
+ bool operator!() const { return _p == 0; }
61
+
62
+ private:
63
+ T *_p;
64
+ };
65
+
66
+ // ------------------------------------------------------------------------
67
+ namespace std
68
+ {
69
+ template <class T>
70
+ inline void swap(spp_sptr<T> &a, spp_sptr<T> &b)
71
+ {
72
+ a.swap(b);
73
+ }
74
+ }
75
+
76
+ #endif // spp_smartptr_h_guard
@@ -0,0 +1,16 @@
1
+ #if !defined(spp_stdint_h_guard)
2
+ #define spp_stdint_h_guard
3
+
4
+ #include <sparsepp/spp_config.h>
5
+
6
+ #if defined(SPP_HAS_CSTDINT) && (__cplusplus >= 201103)
7
+ #include <cstdint>
8
+ #else
9
+ #if defined(__FreeBSD__) || defined(__IBMCPP__) || defined(_AIX)
10
+ #include <inttypes.h>
11
+ #else
12
+ #include <stdint.h>
13
+ #endif
14
+ #endif
15
+
16
+ #endif // spp_stdint_h_guard
@@ -0,0 +1,58 @@
1
+ /**
2
+ Copyright (c) 2016 Mariano Gonzalez
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
21
+ */
22
+
23
+ #ifndef spp_timer_h_guard
24
+ #define spp_timer_h_guard
25
+
26
+ #include <chrono>
27
+
28
+ namespace spp
29
+ {
30
+ template<typename time_unit = std::milli>
31
+ class Timer
32
+ {
33
+ public:
34
+ Timer() { reset(); }
35
+ void reset() { _start = _snap = clock::now(); }
36
+ void snap() { _snap = clock::now(); }
37
+
38
+ float get_total() const { return get_diff<float>(_start, clock::now()); }
39
+ float get_delta() const { return get_diff<float>(_snap, clock::now()); }
40
+
41
+ private:
42
+ using clock = std::chrono::high_resolution_clock;
43
+ using point = std::chrono::time_point<clock>;
44
+
45
+ template<typename T>
46
+ static T get_diff(const point& start, const point& end)
47
+ {
48
+ using duration_t = std::chrono::duration<T, time_unit>;
49
+
50
+ return std::chrono::duration_cast<duration_t>(end - start).count();
51
+ }
52
+
53
+ point _start;
54
+ point _snap;
55
+ };
56
+ }
57
+
58
+ #endif // spp_timer_h_guard
@@ -0,0 +1,122 @@
1
+ #if !defined(spp_traits_h_guard)
2
+ #define spp_traits_h_guard
3
+
4
+ #include <sparsepp/spp_config.h>
5
+
6
+ template<int S, int H> class HashObject; // for Google's benchmark, not in spp namespace!
7
+
8
+ namespace spp_
9
+ {
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // type_traits we need
13
+ // ---------------------------------------------------------------------------
14
+ template<class T, T v>
15
+ struct integral_constant { static const T value = v; };
16
+
17
+ template <class T, T v> const T integral_constant<T, v>::value;
18
+
19
+ typedef integral_constant<bool, true> true_type;
20
+ typedef integral_constant<bool, false> false_type;
21
+
22
+ typedef integral_constant<int, 0> zero_type;
23
+ typedef integral_constant<int, 1> one_type;
24
+ typedef integral_constant<int, 2> two_type;
25
+ typedef integral_constant<int, 3> three_type;
26
+
27
+ template<typename T, typename U> struct is_same : public false_type { };
28
+ template<typename T> struct is_same<T, T> : public true_type { };
29
+
30
+ template<typename T> struct remove_const { typedef T type; };
31
+ template<typename T> struct remove_const<T const> { typedef T type; };
32
+
33
+ template<typename T> struct remove_volatile { typedef T type; };
34
+ template<typename T> struct remove_volatile<T volatile> { typedef T type; };
35
+
36
+ template<typename T> struct remove_cv
37
+ {
38
+ typedef typename remove_const<typename remove_volatile<T>::type>::type type;
39
+ };
40
+
41
+ // ---------------- is_integral ----------------------------------------
42
+ template <class T> struct is_integral;
43
+ template <class T> struct is_integral : false_type { };
44
+ template<> struct is_integral<bool> : true_type { };
45
+ template<> struct is_integral<char> : true_type { };
46
+ template<> struct is_integral<unsigned char> : true_type { };
47
+ template<> struct is_integral<signed char> : true_type { };
48
+ template<> struct is_integral<short> : true_type { };
49
+ template<> struct is_integral<unsigned short> : true_type { };
50
+ template<> struct is_integral<int> : true_type { };
51
+ template<> struct is_integral<unsigned int> : true_type { };
52
+ template<> struct is_integral<long> : true_type { };
53
+ template<> struct is_integral<unsigned long> : true_type { };
54
+ #ifdef SPP_HAS_LONG_LONG
55
+ template<> struct is_integral<long long> : true_type { };
56
+ template<> struct is_integral<unsigned long long> : true_type { };
57
+ #endif
58
+ template <class T> struct is_integral<const T> : is_integral<T> { };
59
+ template <class T> struct is_integral<volatile T> : is_integral<T> { };
60
+ template <class T> struct is_integral<const volatile T> : is_integral<T> { };
61
+
62
+ // ---------------- is_floating_point ----------------------------------------
63
+ template <class T> struct is_floating_point;
64
+ template <class T> struct is_floating_point : false_type { };
65
+ template<> struct is_floating_point<float> : true_type { };
66
+ template<> struct is_floating_point<double> : true_type { };
67
+ template<> struct is_floating_point<long double> : true_type { };
68
+ template <class T> struct is_floating_point<const T> : is_floating_point<T> { };
69
+ template <class T> struct is_floating_point<volatile T> : is_floating_point<T> { };
70
+ template <class T> struct is_floating_point<const volatile T> : is_floating_point<T> { };
71
+
72
+ // ---------------- is_pointer ----------------------------------------
73
+ template <class T> struct is_pointer;
74
+ template <class T> struct is_pointer : false_type { };
75
+ template <class T> struct is_pointer<T*> : true_type { };
76
+ template <class T> struct is_pointer<const T> : is_pointer<T> { };
77
+ template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
78
+ template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
79
+
80
+ // ---------------- is_reference ----------------------------------------
81
+ template <class T> struct is_reference;
82
+ template<typename T> struct is_reference : false_type {};
83
+ template<typename T> struct is_reference<T&> : true_type {};
84
+
85
+ // ---------------- is_relocatable ----------------------------------------
86
+ // relocatable values can be moved around in memory using memcpy and remain
87
+ // correct. Most types are relocatable, an example of a type who is not would
88
+ // be a struct which contains a pointer to a buffer inside itself - this is the
89
+ // case for std::string in gcc 5.
90
+ // ------------------------------------------------------------------------
91
+ template <class T> struct is_relocatable;
92
+ template <class T> struct is_relocatable :
93
+ integral_constant<bool, (is_integral<T>::value || is_floating_point<T>::value)>
94
+ { };
95
+
96
+ template<int S, int H> struct is_relocatable<HashObject<S, H> > : true_type { };
97
+
98
+ template <class T> struct is_relocatable<const T> : is_relocatable<T> { };
99
+ template <class T> struct is_relocatable<volatile T> : is_relocatable<T> { };
100
+ template <class T> struct is_relocatable<const volatile T> : is_relocatable<T> { };
101
+ template <class A, int N> struct is_relocatable<A[N]> : is_relocatable<A> { };
102
+ template <class T, class U> struct is_relocatable<std::pair<T, U> > :
103
+ integral_constant<bool, (is_relocatable<T>::value && is_relocatable<U>::value)>
104
+ { };
105
+
106
+ // A template helper used to select A or B based on a condition.
107
+ // ------------------------------------------------------------
108
+ template<bool cond, typename A, typename B>
109
+ struct if_
110
+ {
111
+ typedef A type;
112
+ };
113
+
114
+ template<typename A, typename B>
115
+ struct if_<false, A, B>
116
+ {
117
+ typedef B type;
118
+ };
119
+
120
+ } // spp_ namespace
121
+
122
+ #endif // spp_traits_h_guard
@@ -0,0 +1,447 @@
1
+ // ----------------------------------------------------------------------
2
+ // Copyright (c) 2016, Steven Gregory Popovitch - greg7mdp@gmail.com
3
+ // All rights reserved.
4
+ //
5
+ // Code derived derived from Boost libraries.
6
+ // Boost software licence reproduced below.
7
+ //
8
+ // Redistribution and use in source and binary forms, with or without
9
+ // modification, are permitted provided that the following conditions are
10
+ // met:
11
+ //
12
+ // * Redistributions of source code must retain the above copyright
13
+ // notice, this list of conditions and the following disclaimer.
14
+ // * Redistributions in binary form must reproduce the above
15
+ // copyright notice, this list of conditions and the following disclaimer
16
+ // in the documentation and/or other materials provided with the
17
+ // distribution.
18
+ // * The name of Steven Gregory Popovitch may not be used to
19
+ // endorse or promote products derived from this software without
20
+ // specific prior written permission.
21
+ //
22
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ // ----------------------------------------------------------------------
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Boost Software License - Version 1.0 - August 17th, 2003
37
+ //
38
+ // Permission is hereby granted, free of charge, to any person or organization
39
+ // obtaining a copy of the software and accompanying documentation covered by
40
+ // this license (the "Software") to use, reproduce, display, distribute,
41
+ // execute, and transmit the Software, and to prepare derivative works of the
42
+ // Software, and to permit third-parties to whom the Software is furnished to
43
+ // do so, all subject to the following:
44
+ //
45
+ // The copyright notices in the Software and this entire statement, including
46
+ // the above license grant, this restriction and the following disclaimer,
47
+ // must be included in all copies of the Software, in whole or in part, and
48
+ // all derivative works of the Software, unless such copies or derivative
49
+ // works are solely in the form of machine-executable object code generated by
50
+ // a source language processor.
51
+ //
52
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54
+ // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
55
+ // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
56
+ // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
57
+ // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
58
+ // DEALINGS IN THE SOFTWARE.
59
+ // ---------------------------------------------------------------------------
60
+
61
+ // ----------------------------------------------------------------------
62
+ // H A S H F U N C T I O N S
63
+ // ----------------------------
64
+ //
65
+ // Implements spp::spp_hash() and spp::hash_combine()
66
+ // ----------------------------------------------------------------------
67
+
68
+ #if !defined(spp_utils_h_guard_)
69
+ #define spp_utils_h_guard_
70
+
71
+ #if defined(_MSC_VER)
72
+ #if (_MSC_VER >= 1600 ) // vs2010 (1900 is vs2015)
73
+ #include <functional>
74
+ #define SPP_HASH_CLASS std::hash
75
+ #else
76
+ #include <hash_map>
77
+ #define SPP_HASH_CLASS stdext::hash_compare
78
+ #endif
79
+ #if (_MSC_FULL_VER < 190021730)
80
+ #define SPP_NO_CXX11_NOEXCEPT
81
+ #endif
82
+ #elif defined __clang__
83
+ #if __has_feature(cxx_noexcept) // what to use here?
84
+ #include <functional>
85
+ #define SPP_HASH_CLASS std::hash
86
+ #else
87
+ #include <tr1/unordered_map>
88
+ #define SPP_HASH_CLASS std::tr1::hash
89
+ #endif
90
+
91
+ #if !__has_feature(cxx_noexcept)
92
+ #define SPP_NO_CXX11_NOEXCEPT
93
+ #endif
94
+ #elif defined(__GNUC__)
95
+ #if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
96
+ #include <functional>
97
+ #define SPP_HASH_CLASS std::hash
98
+
99
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40600
100
+ #define SPP_NO_CXX11_NOEXCEPT
101
+ #endif
102
+ #else
103
+ #include <tr1/unordered_map>
104
+ #define SPP_HASH_CLASS std::tr1::hash
105
+ #define SPP_NO_CXX11_NOEXCEPT
106
+ #endif
107
+ #else
108
+ #include <functional>
109
+ #define SPP_HASH_CLASS std::hash
110
+ #endif
111
+
112
+ #ifdef SPP_NO_CXX11_NOEXCEPT
113
+ #define SPP_NOEXCEPT
114
+ #else
115
+ #define SPP_NOEXCEPT noexcept
116
+ #endif
117
+
118
+ #ifdef SPP_NO_CXX11_CONSTEXPR
119
+ #define SPP_CONSTEXPR
120
+ #else
121
+ #define SPP_CONSTEXPR constexpr
122
+ #endif
123
+
124
+ #define SPP_INLINE
125
+
126
+ #ifndef spp_
127
+ #define spp_ spp
128
+ #endif
129
+
130
+ namespace spp_
131
+ {
132
+
133
+ template <class T> T spp_min(T a, T b) { return a < b ? a : b; }
134
+ template <class T> T spp_max(T a, T b) { return a >= b ? a : b; }
135
+
136
+ template <class T>
137
+ struct spp_hash
138
+ {
139
+ SPP_INLINE size_t operator()(const T &__v) const SPP_NOEXCEPT
140
+ {
141
+ SPP_HASH_CLASS<T> hasher;
142
+ return hasher(__v);
143
+ }
144
+ };
145
+
146
+ template <class T>
147
+ struct spp_hash<T *>
148
+ {
149
+ static size_t spp_log2 (size_t val) SPP_NOEXCEPT
150
+ {
151
+ size_t res = 0;
152
+ while (val > 1)
153
+ {
154
+ val >>= 1;
155
+ res++;
156
+ }
157
+ return res;
158
+ }
159
+
160
+ SPP_INLINE size_t operator()(const T *__v) const SPP_NOEXCEPT
161
+ {
162
+ static const size_t shift = 3; // spp_log2(1 + sizeof(T)); // T might be incomplete!
163
+ const uintptr_t i = (const uintptr_t)__v;
164
+ return static_cast<size_t>(i >> shift);
165
+ }
166
+ };
167
+
168
+ // from http://burtleburtle.net/bob/hash/integer.html
169
+ // fast and efficient for power of two table sizes where we always
170
+ // consider the last bits.
171
+ // ---------------------------------------------------------------
172
+ inline size_t spp_mix_32(uint32_t a)
173
+ {
174
+ a = a ^ (a >> 4);
175
+ a = (a ^ 0xdeadbeef) + (a << 5);
176
+ a = a ^ (a >> 11);
177
+ return static_cast<size_t>(a);
178
+ }
179
+
180
+ // Maybe we should do a more thorough scrambling as described in
181
+ // https://gist.github.com/badboy/6267743
182
+ // -------------------------------------------------------------
183
+ inline size_t spp_mix_64(uint64_t a)
184
+ {
185
+ a = a ^ (a >> 4);
186
+ a = (a ^ 0xdeadbeef) + (a << 5);
187
+ a = a ^ (a >> 11);
188
+ return (size_t)a;
189
+ }
190
+
191
+ template <>
192
+ struct spp_hash<bool> : public std::unary_function<bool, size_t>
193
+ {
194
+ SPP_INLINE size_t operator()(bool __v) const SPP_NOEXCEPT
195
+ { return static_cast<size_t>(__v); }
196
+ };
197
+
198
+ template <>
199
+ struct spp_hash<char> : public std::unary_function<char, size_t>
200
+ {
201
+ SPP_INLINE size_t operator()(char __v) const SPP_NOEXCEPT
202
+ { return static_cast<size_t>(__v); }
203
+ };
204
+
205
+ template <>
206
+ struct spp_hash<signed char> : public std::unary_function<signed char, size_t>
207
+ {
208
+ SPP_INLINE size_t operator()(signed char __v) const SPP_NOEXCEPT
209
+ { return static_cast<size_t>(__v); }
210
+ };
211
+
212
+ template <>
213
+ struct spp_hash<unsigned char> : public std::unary_function<unsigned char, size_t>
214
+ {
215
+ SPP_INLINE size_t operator()(unsigned char __v) const SPP_NOEXCEPT
216
+ { return static_cast<size_t>(__v); }
217
+ };
218
+
219
+ template <>
220
+ struct spp_hash<wchar_t> : public std::unary_function<wchar_t, size_t>
221
+ {
222
+ SPP_INLINE size_t operator()(wchar_t __v) const SPP_NOEXCEPT
223
+ { return static_cast<size_t>(__v); }
224
+ };
225
+
226
+ template <>
227
+ struct spp_hash<int16_t> : public std::unary_function<int16_t, size_t>
228
+ {
229
+ SPP_INLINE size_t operator()(int16_t __v) const SPP_NOEXCEPT
230
+ { return spp_mix_32(static_cast<uint32_t>(__v)); }
231
+ };
232
+
233
+ template <>
234
+ struct spp_hash<uint16_t> : public std::unary_function<uint16_t, size_t>
235
+ {
236
+ SPP_INLINE size_t operator()(uint16_t __v) const SPP_NOEXCEPT
237
+ { return spp_mix_32(static_cast<uint32_t>(__v)); }
238
+ };
239
+
240
+ template <>
241
+ struct spp_hash<int32_t> : public std::unary_function<int32_t, size_t>
242
+ {
243
+ SPP_INLINE size_t operator()(int32_t __v) const SPP_NOEXCEPT
244
+ { return spp_mix_32(static_cast<uint32_t>(__v)); }
245
+ };
246
+
247
+ template <>
248
+ struct spp_hash<uint32_t> : public std::unary_function<uint32_t, size_t>
249
+ {
250
+ SPP_INLINE size_t operator()(uint32_t __v) const SPP_NOEXCEPT
251
+ { return spp_mix_32(static_cast<uint32_t>(__v)); }
252
+ };
253
+
254
+ template <>
255
+ struct spp_hash<int64_t> : public std::unary_function<int64_t, size_t>
256
+ {
257
+ SPP_INLINE size_t operator()(int64_t __v) const SPP_NOEXCEPT
258
+ { return spp_mix_64(static_cast<uint64_t>(__v)); }
259
+ };
260
+
261
+ template <>
262
+ struct spp_hash<uint64_t> : public std::unary_function<uint64_t, size_t>
263
+ {
264
+ SPP_INLINE size_t operator()(uint64_t __v) const SPP_NOEXCEPT
265
+ { return spp_mix_64(static_cast<uint64_t>(__v)); }
266
+ };
267
+
268
+ template <>
269
+ struct spp_hash<float> : public std::unary_function<float, size_t>
270
+ {
271
+ SPP_INLINE size_t operator()(float __v) const SPP_NOEXCEPT
272
+ {
273
+ // -0.0 and 0.0 should return same hash
274
+ uint32_t *as_int = reinterpret_cast<uint32_t *>(&__v);
275
+ return (__v == 0) ? static_cast<size_t>(0) : spp_mix_32(*as_int);
276
+ }
277
+ };
278
+
279
+ template <>
280
+ struct spp_hash<double> : public std::unary_function<double, size_t>
281
+ {
282
+ SPP_INLINE size_t operator()(double __v) const SPP_NOEXCEPT
283
+ {
284
+ // -0.0 and 0.0 should return same hash
285
+ uint64_t *as_int = reinterpret_cast<uint64_t *>(&__v);
286
+ return (__v == 0) ? static_cast<size_t>(0) : spp_mix_64(*as_int);
287
+ }
288
+ };
289
+
290
+ template <class T, int sz> struct Combiner
291
+ {
292
+ inline void operator()(T& seed, T value);
293
+ };
294
+
295
+ template <class T> struct Combiner<T, 4>
296
+ {
297
+ inline void operator()(T& seed, T value)
298
+ {
299
+ seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
300
+ }
301
+ };
302
+
303
+ template <class T> struct Combiner<T, 8>
304
+ {
305
+ inline void operator()(T& seed, T value)
306
+ {
307
+ seed ^= value + T(0xc6a4a7935bd1e995) + (seed << 6) + (seed >> 2);
308
+ }
309
+ };
310
+
311
+ template <class T>
312
+ inline void hash_combine(std::size_t& seed, T const& v)
313
+ {
314
+ spp_::spp_hash<T> hasher;
315
+ Combiner<std::size_t, sizeof(std::size_t)> combiner;
316
+
317
+ combiner(seed, hasher(v));
318
+ }
319
+
320
+ static inline uint32_t s_spp_popcount_default(uint32_t i) SPP_NOEXCEPT
321
+ {
322
+ i = i - ((i >> 1) & 0x55555555);
323
+ i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
324
+ return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
325
+ }
326
+
327
+ static inline uint32_t s_spp_popcount_default(uint64_t x) SPP_NOEXCEPT
328
+ {
329
+ const uint64_t m1 = uint64_t(0x5555555555555555); // binary: 0101...
330
+ const uint64_t m2 = uint64_t(0x3333333333333333); // binary: 00110011..
331
+ const uint64_t m4 = uint64_t(0x0f0f0f0f0f0f0f0f); // binary: 4 zeros, 4 ones ...
332
+ const uint64_t h01 = uint64_t(0x0101010101010101); // the sum of 256 to the power of 0,1,2,3...
333
+
334
+ x -= (x >> 1) & m1; // put count of each 2 bits into those 2 bits
335
+ x = (x & m2) + ((x >> 2) & m2); // put count of each 4 bits into those 4 bits
336
+ x = (x + (x >> 4)) & m4; // put count of each 8 bits into those 8 bits
337
+ return (x * h01)>>56; // returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24)+...
338
+ }
339
+
340
+ #ifdef __APPLE__
341
+ static inline uint32_t count_trailing_zeroes(size_t v) SPP_NOEXCEPT
342
+ {
343
+ size_t x = (v & -v) - 1;
344
+ // sadly sizeof() required to build on macos
345
+ return sizeof(size_t) == 8 ? s_spp_popcount_default((uint64_t)x) : s_spp_popcount_default((uint32_t)x);
346
+ }
347
+
348
+ static inline uint32_t s_popcount(size_t v) SPP_NOEXCEPT
349
+ {
350
+ // sadly sizeof() required to build on macos
351
+ return sizeof(size_t) == 8 ? s_spp_popcount_default((uint64_t)v) : s_spp_popcount_default((uint32_t)v);
352
+ }
353
+ #else
354
+ static inline uint32_t count_trailing_zeroes(size_t v) SPP_NOEXCEPT
355
+ {
356
+ return s_spp_popcount_default((v & -(intptr_t)v) - 1);
357
+ }
358
+
359
+ static inline uint32_t s_popcount(size_t v) SPP_NOEXCEPT
360
+ {
361
+ return s_spp_popcount_default(v);
362
+ }
363
+ #endif
364
+
365
+ // -----------------------------------------------------------
366
+ // -----------------------------------------------------------
367
+ template<class T>
368
+ class libc_allocator
369
+ {
370
+ public:
371
+ typedef T value_type;
372
+ typedef T* pointer;
373
+ typedef ptrdiff_t difference_type;
374
+ typedef const T* const_pointer;
375
+ typedef size_t size_type;
376
+
377
+ libc_allocator() {}
378
+ libc_allocator(const libc_allocator &) {}
379
+ libc_allocator& operator=(const libc_allocator &) { return *this; }
380
+
381
+ #ifndef SPP_NO_CXX11_RVALUE_REFERENCES
382
+ libc_allocator(libc_allocator &&) {}
383
+ libc_allocator& operator=(libc_allocator &&) { return *this; }
384
+ #endif
385
+
386
+ pointer allocate(size_t n, const_pointer /* unused */= 0)
387
+ {
388
+ return static_cast<pointer>(malloc(n * sizeof(T)));
389
+ }
390
+
391
+ void deallocate(pointer p, size_t /* unused */)
392
+ {
393
+ free(p);
394
+ }
395
+
396
+ pointer reallocate(pointer p, size_t new_size)
397
+ {
398
+ return static_cast<pointer>(realloc(p, new_size * sizeof(T)));
399
+ }
400
+
401
+ // extra API to match spp_allocator interface
402
+ pointer reallocate(pointer p, size_t /* old_size */, size_t new_size)
403
+ {
404
+ return static_cast<pointer>(realloc(p, new_size * sizeof(T)));
405
+ }
406
+
407
+ size_type max_size() const
408
+ {
409
+ return static_cast<size_type>(-1) / sizeof(value_type);
410
+ }
411
+
412
+ void construct(pointer p, const value_type& val)
413
+ {
414
+ new(p) value_type(val);
415
+ }
416
+
417
+ void destroy(pointer p) { p->~value_type(); }
418
+
419
+ template<class U>
420
+ struct rebind
421
+ {
422
+ typedef spp_::libc_allocator<U> other;
423
+ };
424
+
425
+ };
426
+
427
+ // forward declaration
428
+ // -------------------
429
+ template<class T>
430
+ class spp_allocator;
431
+
432
+ }
433
+
434
+ template<class T>
435
+ inline bool operator==(const spp_::libc_allocator<T> &, const spp_::libc_allocator<T> &)
436
+ {
437
+ return true;
438
+ }
439
+
440
+ template<class T>
441
+ inline bool operator!=(const spp_::libc_allocator<T> &, const spp_::libc_allocator<T> &)
442
+ {
443
+ return false;
444
+ }
445
+
446
+ #endif // spp_utils_h_guard_
447
+