1 | /* |
2 | * Copyright (C) 2014 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #ifndef Algorithm_h |
27 | #define Algorithm_h |
28 | |
29 | #include "BAssert.h" |
30 | #include <algorithm> |
31 | #include <cstdint> |
32 | #include <cstddef> |
33 | #include <limits> |
34 | #include <string.h> |
35 | #include <type_traits> |
36 | #include <chrono> |
37 | |
38 | namespace bmalloc { |
39 | |
40 | // Versions of min and max that are compatible with compile-time constants. |
41 | template<typename T> constexpr T max(T a, T b) |
42 | { |
43 | return a > b ? a : b; |
44 | } |
45 | |
46 | template<typename T> constexpr T min(T a, T b) |
47 | { |
48 | return a < b ? a : b; |
49 | } |
50 | |
51 | template<typename T> constexpr T mask(T value, uintptr_t mask) |
52 | { |
53 | static_assert(sizeof(T) == sizeof(uintptr_t), "sizeof(T) must be equal to sizeof(uintptr_t)." ); |
54 | return static_cast<T>(static_cast<uintptr_t>(value) & mask); |
55 | } |
56 | |
57 | template<typename T> inline T* mask(T* value, uintptr_t mask) |
58 | { |
59 | return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(value) & mask); |
60 | } |
61 | |
62 | template<typename T> constexpr bool test(T value, uintptr_t mask) |
63 | { |
64 | return !!(reinterpret_cast<uintptr_t>(value) & mask); |
65 | } |
66 | |
67 | template <typename T> |
68 | constexpr bool isPowerOfTwo(T size) |
69 | { |
70 | static_assert(std::is_integral<T>::value, "" ); |
71 | return size && !(size & (size - 1)); |
72 | } |
73 | |
74 | template<typename T> constexpr T roundUpToMultipleOfImpl(size_t divisor, T x) |
75 | { |
76 | static_assert(sizeof(T) == sizeof(uintptr_t), "sizeof(T) must be equal to sizeof(uintptr_t)." ); |
77 | return static_cast<T>((static_cast<uintptr_t>(x) + (divisor - 1)) & ~(divisor - 1)); |
78 | } |
79 | |
80 | template<typename T> inline T roundUpToMultipleOf(size_t divisor, T x) |
81 | { |
82 | BASSERT(isPowerOfTwo(divisor)); |
83 | return roundUpToMultipleOfImpl(divisor, x); |
84 | } |
85 | |
86 | template<size_t divisor, typename T> constexpr T roundUpToMultipleOf(T x) |
87 | { |
88 | static_assert(isPowerOfTwo(divisor), "'divisor' must be a power of two." ); |
89 | return roundUpToMultipleOfImpl(divisor, x); |
90 | } |
91 | |
92 | template<typename T> inline T* roundUpToMultipleOf(size_t divisor, T* x) |
93 | { |
94 | BASSERT(isPowerOfTwo(divisor)); |
95 | return reinterpret_cast<T*>((reinterpret_cast<uintptr_t>(x) + (divisor - 1)) & ~(divisor - 1)); |
96 | } |
97 | |
98 | template<size_t divisor, typename T> inline T* roundUpToMultipleOf(T* x) |
99 | { |
100 | static_assert(isPowerOfTwo(divisor), "'divisor' must be a power of two." ); |
101 | return roundUpToMultipleOf(divisor, x); |
102 | } |
103 | |
104 | template<typename T> inline T roundDownToMultipleOf(size_t divisor, T x) |
105 | { |
106 | BASSERT(isPowerOfTwo(divisor)); |
107 | static_assert(sizeof(T) == sizeof(uintptr_t), "sizeof(T) must be equal to sizeof(uintptr_t)." ); |
108 | return static_cast<T>(mask(static_cast<uintptr_t>(x), ~(divisor - 1ul))); |
109 | } |
110 | |
111 | template<typename T> inline T* roundDownToMultipleOf(size_t divisor, T* x) |
112 | { |
113 | BASSERT(isPowerOfTwo(divisor)); |
114 | return reinterpret_cast<T*>(mask(reinterpret_cast<uintptr_t>(x), ~(divisor - 1ul))); |
115 | } |
116 | |
117 | template<size_t divisor, typename T> constexpr T roundDownToMultipleOf(T x) |
118 | { |
119 | static_assert(isPowerOfTwo(divisor), "'divisor' must be a power of two." ); |
120 | return roundDownToMultipleOf(divisor, x); |
121 | } |
122 | |
123 | template<typename T> inline void divideRoundingUp(T numerator, T denominator, T& quotient, T& remainder) |
124 | { |
125 | // We expect the compiler to emit a single divide instruction to extract both the quotient and the remainder. |
126 | quotient = numerator / denominator; |
127 | remainder = numerator % denominator; |
128 | if (remainder) |
129 | quotient += 1; |
130 | } |
131 | |
132 | template<typename T> inline T divideRoundingUp(T numerator, T denominator) |
133 | { |
134 | return (numerator + denominator - 1) / denominator; |
135 | } |
136 | |
137 | template<typename T> inline T roundUpToMultipleOfNonPowerOfTwo(size_t divisor, T x) |
138 | { |
139 | return divideRoundingUp(x, divisor) * divisor; |
140 | } |
141 | |
142 | // Version of sizeof that returns 0 for empty classes. |
143 | |
144 | template<typename T> constexpr size_t sizeOf() |
145 | { |
146 | return std::is_empty<T>::value ? 0 : sizeof(T); |
147 | } |
148 | |
149 | template<typename T> constexpr size_t bitCount() |
150 | { |
151 | return sizeof(T) * 8; |
152 | } |
153 | |
154 | #if BOS(WINDOWS) |
155 | template<int depth> __forceinline constexpr unsigned long clzl(unsigned long value) |
156 | { |
157 | return value & (1UL << (bitCount<unsigned long>() - 1)) ? 0 : 1 + clzl<depth - 1>(value << 1); |
158 | } |
159 | |
160 | template<> __forceinline constexpr unsigned long clzl<1>(unsigned long value) |
161 | { |
162 | return 0; |
163 | } |
164 | |
165 | __forceinline constexpr unsigned long __builtin_clzl(unsigned long value) |
166 | { |
167 | return value == 0 ? 32 : clzl<bitCount<unsigned long>()>(value); |
168 | } |
169 | #endif |
170 | |
171 | constexpr unsigned long log2(unsigned long value) |
172 | { |
173 | return bitCount<unsigned long>() - 1 - __builtin_clzl(value); |
174 | } |
175 | |
176 | #define BOFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000) |
177 | |
178 | template<typename T> |
179 | bool findBitInWord(T word, size_t& index, size_t endIndex, bool value) |
180 | { |
181 | static_assert(std::is_unsigned<T>::value, "Type used in findBitInWord must be unsigned" ); |
182 | |
183 | word >>= index; |
184 | |
185 | while (index < endIndex) { |
186 | if ((word & 1) == static_cast<T>(value)) |
187 | return true; |
188 | index++; |
189 | word >>= 1; |
190 | } |
191 | |
192 | index = endIndex; |
193 | return false; |
194 | } |
195 | |
196 | } // namespace bmalloc |
197 | |
198 | #endif // Algorithm_h |
199 | |