sparsam 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+