Coverage Report

Created: 2026-04-03 03:38

/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