/home/runner/work/slang/slang/source/core/slang-uint-set.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "slang-uint-set.h" |
2 | | |
3 | | namespace Slang |
4 | | { |
5 | | |
6 | | Index UIntSet::getLSBZero() |
7 | 5 | { |
8 | 5 | uint64_t offset = 0; |
9 | 5 | for (Element& element : this->m_buffer) |
10 | 5 | { |
11 | | // Flip all bits so bitscanForward can find a 0 bit |
12 | 5 | Element flippedElement = ~element; |
13 | | |
14 | | // continue if we don't have 0 bits |
15 | 5 | if (flippedElement == 0) |
16 | 0 | { |
17 | 0 | offset += sizeof(Element) * 8; |
18 | 0 | continue; |
19 | 0 | } |
20 | | |
21 | | // Get LSBZero of current Block, add with offset |
22 | 5 | return bitscanForward(flippedElement) + offset; |
23 | 5 | } |
24 | 0 | return offset; |
25 | 5 | } |
26 | | |
27 | | UIntSet& UIntSet::operator=(UIntSet&& other) |
28 | 5.49M | { |
29 | 5.49M | m_buffer = _Move(other.m_buffer); |
30 | 5.49M | return *this; |
31 | 5.49M | } |
32 | | |
33 | | UIntSet& UIntSet::operator=(const UIntSet& other) |
34 | 807k | { |
35 | 807k | m_buffer = other.m_buffer; |
36 | 807k | return *this; |
37 | 807k | } |
38 | | |
39 | | HashCode UIntSet::getHashCode() const |
40 | 2.55M | { |
41 | 2.55M | int rs = 0; |
42 | 2.55M | for (auto val : m_buffer) |
43 | 5.34M | rs ^= val; |
44 | 2.55M | return rs; |
45 | 2.55M | } |
46 | | |
47 | | void UIntSet::resizeAndUnsetAll(UInt val) |
48 | 6.34M | { |
49 | | // TODO(JS): This could be faster in that if the resize is larger the additional area is cleared |
50 | | // twice |
51 | 6.34M | resize(val); |
52 | 6.34M | unsetAll(); |
53 | 6.34M | } |
54 | | |
55 | | void UIntSet::setAll() |
56 | 0 | { |
57 | 0 | ::memset(m_buffer.getBuffer(), -1, m_buffer.getCount() * sizeof(Element)); |
58 | 0 | } |
59 | | |
60 | | void UIntSet::resize(UInt size) |
61 | 11.8M | { |
62 | 11.8M | const Index newCount = Index((size + kElementMask) >> kElementShift); |
63 | 11.8M | resizeBackingBufferDirectly(newCount); |
64 | 11.8M | } |
65 | | |
66 | | void UIntSet::unsetAll() |
67 | 6.34M | { |
68 | 6.34M | if (m_buffer.getCount() > 0) |
69 | 6.34M | ::memset(m_buffer.getBuffer(), 0, m_buffer.getCount() * sizeof(Element)); |
70 | 6.34M | } |
71 | | |
72 | | bool UIntSet::isEmpty() const |
73 | 44 | { |
74 | 44 | return _areAllZero(m_buffer.getBuffer(), m_buffer.getCount()); |
75 | 44 | } |
76 | | |
77 | | void UIntSet::clearAndDeallocate() |
78 | 0 | { |
79 | 0 | m_buffer.clearAndDeallocate(); |
80 | 0 | } |
81 | | |
82 | | void UIntSet::unionWith(const UIntSet& set) |
83 | 11.2M | { |
84 | 11.2M | const Index minCount = Math::Min(set.m_buffer.getCount(), m_buffer.getCount()); |
85 | 70.8M | for (Index i = 0; i < minCount; i++) |
86 | 59.6M | { |
87 | 59.6M | m_buffer[i] |= set.m_buffer[i]; |
88 | 59.6M | } |
89 | | |
90 | 11.2M | if (set.m_buffer.getCount() > m_buffer.getCount()) |
91 | 60 | m_buffer.addRange( |
92 | 60 | set.m_buffer.getBuffer() + m_buffer.getCount(), |
93 | 60 | set.m_buffer.getCount() - m_buffer.getCount()); |
94 | 11.2M | } |
95 | | |
96 | | bool UIntSet::operator==(const UIntSet& set) const |
97 | 1.45M | { |
98 | 1.45M | const Index aCount = m_buffer.getCount(); |
99 | 1.45M | const auto aElems = m_buffer.getBuffer(); |
100 | | |
101 | 1.45M | const Index bCount = set.m_buffer.getCount(); |
102 | 1.45M | const auto bElems = set.m_buffer.getBuffer(); |
103 | | |
104 | 1.45M | if (aCount == 0 || bCount == 0) |
105 | 155 | return aCount == bCount; |
106 | | |
107 | 1.45M | const Index minCount = Math::Min(aCount, bCount); |
108 | | |
109 | 1.45M | return ::memcmp(aElems, bElems, minCount * sizeof(Element)) == 0 && |
110 | 1.45M | _areAllZero(aElems + minCount, aCount - minCount) && |
111 | 1.45M | _areAllZero(bElems + minCount, bCount - minCount); |
112 | 1.45M | } |
113 | | |
114 | | void UIntSet::intersectWith(const UIntSet& set) |
115 | 0 | { |
116 | 0 | if (set.m_buffer.getCount() < m_buffer.getCount()) |
117 | 0 | ::memset( |
118 | 0 | m_buffer.getBuffer() + set.m_buffer.getCount(), |
119 | 0 | 0, |
120 | 0 | (m_buffer.getCount() - set.m_buffer.getCount()) * sizeof(Element)); |
121 | |
|
122 | 0 | const Index minCount = Math::Min(set.m_buffer.getCount(), m_buffer.getCount()); |
123 | 0 | for (Index i = 0; i < minCount; i++) |
124 | 0 | { |
125 | 0 | m_buffer[i] &= set.m_buffer[i]; |
126 | 0 | } |
127 | 0 | } |
128 | | |
129 | | void UIntSet::subtractWith(const UIntSet& set) |
130 | 5 | { |
131 | 5 | const Index minCount = Math::Min(this->m_buffer.getCount(), set.m_buffer.getCount()); |
132 | 11 | for (Index i = 0; i < minCount; i++) |
133 | 6 | { |
134 | 6 | this->m_buffer[i] = this->m_buffer[i] & (~set.m_buffer[i]); |
135 | 6 | } |
136 | 5 | } |
137 | | |
138 | | /* static */ void UIntSet::calcUnion(UIntSet& outRs, const UIntSet& set1, const UIntSet& set2) |
139 | 0 | { |
140 | 0 | outRs.resizeBackingBufferDirectly( |
141 | 0 | Math::Max(set1.m_buffer.getCount(), set2.m_buffer.getCount())); |
142 | 0 | outRs.unsetAll(); |
143 | 0 | for (Index i = 0; i < set1.m_buffer.getCount(); i++) |
144 | 0 | outRs.m_buffer[i] |= set1.m_buffer[i]; |
145 | 0 | for (Index i = 0; i < set2.m_buffer.getCount(); i++) |
146 | 0 | outRs.m_buffer[i] |= set2.m_buffer[i]; |
147 | 0 | } |
148 | | |
149 | | /* static */ void UIntSet::calcIntersection( |
150 | | UIntSet& outRs, |
151 | | const UIntSet& set1, |
152 | | const UIntSet& set2) |
153 | 2.72M | { |
154 | 2.72M | const Index minCount = Math::Min(set1.m_buffer.getCount(), set2.m_buffer.getCount()); |
155 | 2.72M | outRs.resizeBackingBufferDirectly(minCount); |
156 | | |
157 | 5.52M | for (Index i = 0; i < minCount; i++) |
158 | 2.79M | outRs.m_buffer[i] = set1.m_buffer[i] & set2.m_buffer[i]; |
159 | 2.72M | } |
160 | | |
161 | | /* static */ void UIntSet::calcSubtract(UIntSet& outRs, const UIntSet& set1, const UIntSet& set2) |
162 | 823 | { |
163 | 823 | const auto set1Count = set1.m_buffer.getCount(); |
164 | 823 | const auto set2Count = set2.m_buffer.getCount(); |
165 | | |
166 | 823 | outRs.resizeBackingBufferDirectly(set1Count); |
167 | | |
168 | 3.38k | for (Index i = 0; i < set1Count; i++) |
169 | 2.55k | { |
170 | 2.55k | if (i < set2Count) |
171 | 2.08k | { |
172 | 2.08k | outRs.m_buffer[i] = set1.m_buffer[i] & (~set2.m_buffer[i]); |
173 | 2.08k | } |
174 | 472 | else |
175 | 472 | { |
176 | | // If `set2` is smaller, copy the remaining values from `set1` |
177 | 472 | outRs.m_buffer[i] = set1.m_buffer[i]; |
178 | 472 | } |
179 | 2.55k | } |
180 | 823 | } |
181 | | |
182 | | /* static */ bool UIntSet::hasIntersection(const UIntSet& set1, const UIntSet& set2) |
183 | 0 | { |
184 | 0 | const Index minCount = Math::Min(set1.m_buffer.getCount(), set2.m_buffer.getCount()); |
185 | 0 | for (Index i = 0; i < minCount; i++) |
186 | 0 | { |
187 | 0 | if (set1.m_buffer[i] & set2.m_buffer[i]) |
188 | 0 | return true; |
189 | 0 | } |
190 | 0 | return false; |
191 | 0 | } |
192 | | |
193 | | Index UIntSet::countElements() const |
194 | 674 | { |
195 | | // TODO: This can be made faster using SIMD intrinsics to count set bits. |
196 | 674 | uint64_t tmp; |
197 | 674 | constexpr Index loopSize = |
198 | 674 | ((sizeof(Element) / sizeof(tmp)) != 0) ? sizeof(Element) / sizeof(tmp) : 1; |
199 | 674 | Index count = 0; |
200 | 2.85k | for (auto index = 0; index < this->m_buffer.getCount(); index++) |
201 | 2.18k | { |
202 | 4.36k | for (auto i = 0; i < loopSize; i++) |
203 | 2.18k | { |
204 | 2.18k | tmp = m_buffer[index] >> (sizeof(tmp) * i); |
205 | 2.18k | tmp = tmp - ((tmp >> 1) & 0x5555555555555555); |
206 | 2.18k | tmp = (tmp & 0x3333333333333333) + ((tmp >> 2) & 0x3333333333333333); |
207 | 2.18k | count += ((tmp + (tmp >> 4) & 0xF0F0F0F0F0F0F0F) * 0x101010101010101) >> 56; |
208 | 2.18k | } |
209 | 2.18k | } |
210 | 674 | return count; |
211 | 674 | } |
212 | | |
213 | | } // namespace Slang |