• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifdef PANDA_CATCH2
17 #include "util/bit_vector.h"
18 #include "util/set_operations.h"
19 #include "util/range.h"
20 #include "util/lazy.h"
21 
22 #include <catch2/catch.hpp>
23 #include <rapidcheck/catch.h>
24 #include "util/tests/environment.h"
25 
26 #include <cstdint>
27 #include <initializer_list>
28 #include <string>
29 #include <set>
30 
31 using namespace panda::verifier;
32 
33 using StdSet = std::set<size_t>;
34 
35 struct BSet {
36     StdSet Indices;
37     BitVector Bits;
38 
IsEqualBSet39     bool IsEqual() const
40     {
41         if (Bits.SetBitsCount() != Indices.size()) {
42             return false;
43         }
44         for (const auto &elem : Indices) {
45             if (!Bits[elem]) {
46                 return false;
47             }
48         }
49         return true;
50     }
51 };
52 
showValue(const BSet & bitset,std::ostream & os)53 void showValue(const BSet &bitset, std::ostream &os)
54 {
55     os << "BitSet{ .Indices {";
56     bool comma = false;
57     for (auto idx : bitset.Indices) {
58         if (comma) {
59             os << ", ";
60         }
61         comma = true;
62         os << idx;
63     }
64     os << "}, ";
65     os << ".Bits = {";
66     for (size_t idx = 0; idx < bitset.Bits.size(); ++idx) {
67         os << (static_cast<int>(bitset.Bits[idx]) ? '1' : '0');
68         if (((idx + 1) & 0x7) == 0) {
69             os << ' ';
70         }
71         if (((idx + 1) & 0x1F) == 0) {
72             os << ' ';
73         }
74     }
75     os << "} }";
76 }
77 
78 namespace rc {
79 
80 constexpr size_t max_value = 1024U;
81 auto value_gen = gen::inRange<size_t>(0, max_value);
82 
83 template <>
84 struct Arbitrary<BSet> {
arbitraryrc::Arbitrary85     static Gen<BSet> arbitrary()
86     {
87         auto set_n_inc = gen::pair(gen::container<std::set<size_t>>(value_gen), gen::inRange(1, 100));  // N = 100
88         return gen::map(set_n_inc, [](auto param_set_n_inc) {
89             auto &[set, inc] = param_set_n_inc;
90             size_t size = (set.empty() ? 0 : *set.rbegin()) + inc;
91             BitVector bits {size};
92             for (const auto &idx : set) {
93                 bits[idx] = 1;
94             }
95             return BSet {set, bits};
96         });
97     }
98 };
99 
100 template <>
101 struct Arbitrary<Range<size_t>> {
arbitraryrc::Arbitrary102     static Gen<Range<size_t>> arbitrary()
103     {
104         return gen::map(gen::pair(value_gen, value_gen), [](auto pair) {
105             return Range<size_t> {std::min(pair.first, pair.second), std::max(pair.first, pair.second)};
106         });
107     }
108 };
109 
110 }  // namespace rc
111 
112 namespace panda::verifier::test {
113 
114 using namespace rc;
115 
116 using Interval = panda::verifier::Range<size_t>;
117 using Intervals = std::initializer_list<Interval>;
118 
ClassifySize(std::string name,size_t size,const Intervals & intervals)119 void ClassifySize(std::string name, size_t size, const Intervals &intervals)
120 {
121     for (const auto &i : intervals) {
122         RC_CLASSIFY(i.Contains(size), name + " " + std::to_string(i));
123     }
124 }
125 
126 const EnvOptions Options {"VERIFIER_TEST"};
127 
128 Intervals stat_intervals = {{0, 10U}, {11U, 50U}, {51U, 100U}, {101U, max_value}};
129 
stat(const BSet & bitset)130 void stat(const BSet &bitset)
131 {
132     if (Options.Get<bool>("verbose", false)) {
133         ClassifySize("Bits.size() in", bitset.Bits.size(), stat_intervals);
134         ClassifySize("Indices.size() in", bitset.Indices.size(), stat_intervals);
135     }
136 }
137 
Universum(size_t size)138 StdSet Universum(size_t size)
139 {
140     return ToSet<StdSet>(Interval(0, size - 1));
141 }
142 
143 TEST_CASE("Test bitvector", "verifier_bitvector")
144 {
145     SECTION("Basic tests")
146     {
__anonea1bced30302(const BSet &bit_set) 147         prop("SetBitsCount()", [](const BSet &bit_set) {
148             stat(bit_set);
149             RC_ASSERT(bit_set.Bits.SetBitsCount() == bit_set.Indices.size());
150         });
__anonea1bced30402(const BSet &bit_set) 151         prop("operator=", [](const BSet &bit_set) {
152             stat(bit_set);
153             auto bits = bit_set.Bits;
154             RC_ASSERT(bits.size() == bit_set.Bits.size());
155             for (size_t idx = 0; idx < bits.size(); ++idx) {
156                 RC_ASSERT(bits[idx] == bit_set.Bits[idx]);
157             }
158             RC_ASSERT(bits.SetBitsCount() == bit_set.Bits.SetBitsCount());
159         });
__anonea1bced30502(BSet &&bset) 160         prop("clr()", [](BSet &&bset) {
161             stat(bset);
162             bset.Bits.clr();
163             RC_ASSERT(bset.Bits.SetBitsCount() == 0U);
164         });
__anonea1bced30602(BSet &&bset) 165         prop("set()", [](BSet &&bset) {
166             stat(bset);
167             bset.Bits.set();
168             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Bits.size());
169         });
__anonea1bced30702(BSet &&bset) 170         prop("invert()", [](BSet &&bset) {
171             stat(bset);
172             auto zero_bits = bset.Bits.size() - bset.Bits.SetBitsCount();
173             bset.Bits.invert();
174             RC_ASSERT(bset.Bits.SetBitsCount() == zero_bits);
175         });
__anonea1bced30802(BSet &&bset, std::set<size_t> &&indices) 176         prop("Clr(size_t idx)", [](BSet &&bset, std::set<size_t> &&indices) {
177             stat(bset);
178             auto size = bset.Bits.size();
179             for (const auto &idx : indices) {
180                 bset.Bits.Clr(idx % size);
181                 bset.Indices.erase(idx % size);
182             }
183             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Indices.size());
184         });
__anonea1bced30902(BSet &&bset, std::set<size_t> &&indices) 185         prop("Set(size_t idx)", [](BSet &&bset, std::set<size_t> &&indices) {
186             stat(bset);
187             auto size = bset.Bits.size();
188             for (const auto &idx : indices) {
189                 auto i = idx % size;
190                 bset.Bits.Set(i);
191                 bset.Indices.insert(i);
192             }
193             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Indices.size());
194         });
__anonea1bced30a02(BSet &&bset, std::set<size_t> &&indices) 195         prop("invert(size_t idx)", [](BSet &&bset, std::set<size_t> &&indices) {
196             stat(bset);
197             auto size = bset.Bits.size();
198             for (const auto &idx : indices) {
199                 auto i = idx % size;
200                 bset.Bits.invert(i);
201                 if (bset.Indices.count(i) > 0) {
202                     bset.Indices.erase(i);
203                 } else {
204                     bset.Indices.insert(i);
205                 }
206             }
207             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Indices.size());
208         });
__anonea1bced30b02(BSet &&bset, Interval &&interval) 209         prop("clr(size_t from, size_t to)", [](BSet &&bset, Interval &&interval) {
210             RC_PRE(interval.End() < bset.Bits.size());
211             stat(bset);
212             bset.Bits.Clr(interval.Start(), interval.End());
213             for (auto idx : interval) {
214                 bset.Indices.erase(idx);
215             }
216             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Indices.size());
217         });
__anonea1bced30c02(BSet &&bset, Interval &&interval) 218         prop("set(size_t from, size_t to)", [](BSet &&bset, Interval &&interval) {
219             RC_PRE(interval.End() < bset.Bits.size());
220             stat(bset);
221             bset.Bits.Set(interval.Start(), interval.End());
222             for (auto idx : interval) {
223                 bset.Indices.insert(idx);
224             }
225             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Indices.size());
226         });
__anonea1bced30d02(BSet &&bset, Interval &&interval) 227         prop("invert(size_t from, size_t to)", [](BSet &&bset, Interval &&interval) {
228             RC_PRE(interval.End() < bset.Bits.size());
229             stat(bset);
230             bset.Bits.invert(interval.Start(), interval.End());
231             for (auto idx : interval) {
232                 if (bset.Indices.count(idx) > 0) {
233                     bset.Indices.erase(idx);
234                 } else {
235                     bset.Indices.insert(idx);
236                 }
237             }
238             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Indices.size());
239         });
__anonea1bced30e02(BSet &&lhs, BSet &&rhs) 240         prop("operator&=", [](BSet &&lhs, BSet &&rhs) {
241             stat(rhs);
242             stat(lhs);
243             lhs.Bits &= rhs.Bits;
244             lhs.Indices = SetIntersection(lhs.Indices, rhs.Indices);
245             RC_ASSERT(lhs.IsEqual());
246         });
__anonea1bced30f02(BSet &&lhs, BSet &&rhs) 247         prop("operator|=", [](BSet &&lhs, BSet &&rhs) {
248             stat(rhs);
249             stat(lhs);
250             StdSet universum = Universum(std::max(lhs.Bits.size(), rhs.Bits.size()));
251             StdSet clamped = SetIntersection(rhs.Indices, universum);
252             lhs.Bits |= rhs.Bits;
253             lhs.Indices = SetUnion(lhs.Indices, clamped);
254             RC_ASSERT(lhs.IsEqual());
255         });
__anonea1bced31002(BSet &&lhs, BSet &&rhs) 256         prop("operator^=", [](BSet &&lhs, BSet &&rhs) {
257             stat(rhs);
258             stat(lhs);
259             lhs.Bits ^= rhs.Bits;
260             lhs.Indices = SetDifference(SetUnion(lhs.Indices, rhs.Indices), SetIntersection(lhs.Indices, rhs.Indices));
261             RC_ASSERT(lhs.IsEqual());
262         });
__anonea1bced31102(BSet &&bset, size_t new_size) 263         prop("resize(size_t)", [](BSet &&bset, size_t new_size) {
264             stat(bset);
265             new_size %= bset.Bits.size();
266             bset.Bits.resize(new_size);
267             auto universum = Universum(new_size);
268             bset.Indices = SetIntersection(universum, bset.Indices);
269             RC_ASSERT(bset.Bits.SetBitsCount() == bset.Indices.size());
270             RC_ASSERT(bset.Bits.size() == new_size);
271         });
272     }
273     SECTION("Iterators")
274     {
__anonea1bced31202(BSet &&bset) 275         prop("for_all_idx_val(Handler)", [](BSet &&bset) {
276             stat(bset);
277             StdSet selected;
278             auto handler = [&selected](auto idx, auto val) {
279                 while (val) {
280                     if (val & 1U) {
281                         selected.insert(idx);
282                     }
283                     val >>= 1U;
284                     ++idx;
285                 }
286                 return true;
287             };
288             bset.Bits.for_all_idx_val(handler);
289             RC_ASSERT(selected == bset.Indices);
290         });
__anonea1bced31402(BSet &&bset) 291         prop("for_all_idx_of<1>(Handler)", [](BSet &&bset) {
292             stat(bset);
293             StdSet result;
294             bset.Bits.for_all_idx_of<1>([&result](auto idx) {
295                 result.insert(idx);
296                 return true;
297             });
298             RC_ASSERT(result == bset.Indices);
299         });
__anonea1bced31602(BSet &&bset) 300         prop("for_all_idx_of<0>(Handler)", [](BSet &&bset) {
301             stat(bset);
302             StdSet result;
303             bset.Bits.for_all_idx_of<0>([&result](auto idx) {
304                 result.insert(idx);
305                 return true;
306             });
307             StdSet universum = Universum(bset.Bits.size());
308             RC_ASSERT(result == SetDifference(universum, bset.Indices));
309         });
310     }
311     SECTION("Lazy iterators")
312     {
__anonea1bced31802(BSet &&bset) 313         prop("LazyIndicesOf<1>(from, to)", [](BSet &&bset) {
314             stat(bset);
315             size_t from = *gen::inRange<size_t>(0, bset.Bits.size() - 1);
316             size_t to = *gen::oneOf(gen::inRange<size_t>(from, bset.Bits.size()),
317                                     gen::just(std::numeric_limits<size_t>::max()));
318             auto result = ContainerOf<StdSet>(bset.Bits.LazyIndicesOf<1>(from, to));
319             StdSet expected = bset.Indices;
320             if (from > 0) {
321                 expected.erase(expected.begin(), expected.lower_bound(from));
322             }
323             if (!expected.empty() && to < *expected.rbegin()) {
324                 expected.erase(expected.upper_bound(to), expected.end());
325             }
326             RC_ASSERT(result == expected);
327         });
__anonea1bced31902(BSet &&bset) 328         prop("LazyIndicesOf<0>(from)", [](BSet &&bset) {
329             stat(bset);
330             size_t from = *gen::inRange<size_t>(0, bset.Bits.size() - 1);
331             auto result = ContainerOf<StdSet>(bset.Bits.LazyIndicesOf<0>(from));
332             StdSet universum = Universum(bset.Bits.size());
333             StdSet expected = SetDifference(universum, bset.Indices);
334             if (from > 0) {
335                 expected.erase(expected.begin(), expected.lower_bound(from));
336             }
337             RC_ASSERT(result == expected);
338         });
339     }
340     SECTION("Power of folded bitsets")
341     {
__anonea1bced31a02(BSet &&bset1, BSet &&bset2) 342         prop("power_of_and(arg,arg)", [](BSet &&bset1, BSet &&bset2) {
343             stat(bset1);
344             stat(bset2);
345             auto result = BitVector::power_of_and(bset1.Bits, bset2.Bits);
346             RC_ASSERT(result == SetIntersection(bset1.Indices, bset2.Indices).size());
347         });
__anonea1bced31b02(BSet &&bset1, BSet &&bset2, BSet &&bset3) 348         prop("power_of_and(arg,arg,arg)", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
349             stat(bset1);
350             stat(bset2);
351             stat(bset3);
352             auto result = BitVector::power_of_and(bset1.Bits, bset2.Bits, bset3.Bits);
353             RC_ASSERT(result == SetIntersection(bset1.Indices, bset2.Indices, bset3.Indices).size());
354         });
__anonea1bced31c02(BSet &&bset1, BSet &&bset2) 355         prop("power_of_or(arg,arg)", [](BSet &&bset1, BSet &&bset2) {
356             stat(bset1);
357             stat(bset2);
358             auto result = BitVector::power_of_or(bset1.Bits, bset2.Bits);
359             auto size = std::min(bset1.Bits.size(), bset2.Bits.size());
360             auto universum = Universum(size);
361             RC_ASSERT(result == SetIntersection(universum, SetUnion(bset1.Indices, bset2.Indices)).size());
362         });
__anonea1bced31d02(BSet &&bset1, BSet &&bset2, BSet &&bset3) 363         prop("power_of_or(arg,arg,arg)", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
364             stat(bset1);
365             stat(bset2);
366             stat(bset3);
367             auto result = BitVector::power_of_or(bset1.Bits, bset2.Bits, bset3.Bits);
368             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
369             auto universum = Universum(size);
370             RC_ASSERT(result ==
371                       SetIntersection(universum, SetUnion(bset1.Indices, bset2.Indices, bset3.Indices)).size());
372         });
__anonea1bced31e02(BSet &&bset1, BSet &&bset2) 373         prop("power_of_xor(arg,arg)", [](BSet &&bset1, BSet &&bset2) {
374             stat(bset1);
375             stat(bset2);
376             auto result = BitVector::power_of_xor(bset1.Bits, bset2.Bits);
377             auto size = std::min(bset1.Bits.size(), bset2.Bits.size());
378             auto universum = Universum(size);
379             auto set_result = SetIntersection(universum, SetDifference(SetUnion(bset1.Indices, bset2.Indices),
380                                                                        SetIntersection(bset1.Indices, bset2.Indices)));
381             RC_ASSERT(result == set_result.size());
382         });
__anonea1bced31f02(BSet &&bset1, BSet &&bset2, BSet &&bset3) 383         prop("power_of_xor(arg,arg,arg)", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
384             stat(bset1);
385             stat(bset2);
386             stat(bset3);
387             auto result = BitVector::power_of_xor(bset1.Bits, bset2.Bits, bset3.Bits);
388             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
389             auto universum = Universum(size);
390             auto xor1 =
391                 SetDifference(SetUnion(bset1.Indices, bset2.Indices), SetIntersection(bset1.Indices, bset2.Indices));
392             auto xor2 = SetDifference(SetUnion(xor1, bset3.Indices), SetIntersection(xor1, bset3.Indices));
393             auto set_result = SetIntersection(universum, xor2);
394             RC_ASSERT(result == set_result.size());
395         });
__anonea1bced32002(BSet &&bset1, BSet &&bset2) 396         prop("power_of_and_not(arg,arg)", [](BSet &&bset1, BSet &&bset2) {
397             stat(bset1);
398             stat(bset2);
399             auto result = BitVector::power_of_and_not(bset1.Bits, bset2.Bits);
400             auto size = std::min(bset1.Bits.size(), bset2.Bits.size());
401             auto universum = Universum(size);
402             auto set_result = SetIntersection(universum, SetDifference(bset1.Indices, bset2.Indices));
403             RC_ASSERT(result == set_result.size());
404         });
405     }
406     SECTION("Lazy iterators over folded bitsets")
407     {
__anonea1bced32102(BSet &&bset1, BSet &&bset2, BSet &&bset3) 408         prop("lazy_and_then_indices_of<1>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
409             stat(bset1);
410             stat(bset2);
411             stat(bset3);
412             auto result =
413                 ContainerOf<StdSet>(BitVector::lazy_and_then_indices_of<1>(bset1.Bits, bset2.Bits, bset3.Bits));
414             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
415             auto universum = Universum(size);
416             auto set_result = SetIntersection(universum, bset1.Indices, bset2.Indices, bset3.Indices);
417             RC_ASSERT(result == set_result);
418         });
__anonea1bced32202(BSet &&bset1, BSet &&bset2, BSet &&bset3) 419         prop("lazy_and_then_indices_of<0>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
420             stat(bset1);
421             stat(bset2);
422             stat(bset3);
423             auto result =
424                 ContainerOf<StdSet>(BitVector::lazy_and_then_indices_of<0>(bset1.Bits, bset2.Bits, bset3.Bits));
425             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
426             auto universum = Universum(size);
427             auto set_result = SetDifference(universum, SetIntersection(bset1.Indices, bset2.Indices, bset3.Indices));
428             RC_ASSERT(result == set_result);
429         });
__anonea1bced32302(BSet &&bset1, BSet &&bset2, BSet &&bset3) 430         prop("lazy_or_then_indices_of<1>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
431             stat(bset1);
432             stat(bset2);
433             stat(bset3);
434             auto result =
435                 ContainerOf<StdSet>(BitVector::lazy_or_then_indices_of<1>(bset1.Bits, bset2.Bits, bset3.Bits));
436             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
437             auto universum = Universum(size);
438             auto set_result = SetIntersection(universum, SetUnion(bset1.Indices, bset2.Indices, bset3.Indices));
439             RC_ASSERT(result == set_result);
440         });
__anonea1bced32402(BSet &&bset1, BSet &&bset2, BSet &&bset3) 441         prop("lazy_or_then_indices_of<0>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
442             stat(bset1);
443             stat(bset2);
444             stat(bset3);
445             auto result =
446                 ContainerOf<StdSet>(BitVector::lazy_or_then_indices_of<0>(bset1.Bits, bset2.Bits, bset3.Bits));
447             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
448             auto universum = Universum(size);
449             auto set_result = SetDifference(universum, SetUnion(bset1.Indices, bset2.Indices, bset3.Indices));
450             RC_ASSERT(result == set_result);
451         });
__anonea1bced32502(BSet &&bset1, BSet &&bset2, BSet &&bset3) 452         prop("lazy_xor_then_indices_of<1>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
453             stat(bset1);
454             stat(bset2);
455             stat(bset3);
456             auto result =
457                 ContainerOf<StdSet>(BitVector::lazy_xor_then_indices_of<1>(bset1.Bits, bset2.Bits, bset3.Bits));
458             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
459             auto universum = Universum(size);
460             auto xor1 =
461                 SetDifference(SetUnion(bset1.Indices, bset2.Indices), SetIntersection(bset1.Indices, bset2.Indices));
462             auto xor2 = SetDifference(SetUnion(xor1, bset3.Indices), SetIntersection(xor1, bset3.Indices));
463             auto set_result = SetIntersection(universum, xor2);
464             RC_ASSERT(result == set_result);
465         });
__anonea1bced32602(BSet &&bset1, BSet &&bset2, BSet &&bset3) 466         prop("lazy_xor_then_indices_of<0>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
467             stat(bset1);
468             stat(bset2);
469             stat(bset3);
470             auto result =
471                 ContainerOf<StdSet>(BitVector::lazy_xor_then_indices_of<0>(bset1.Bits, bset2.Bits, bset3.Bits));
472             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
473             auto universum = Universum(size);
474             auto xor1 =
475                 SetDifference(SetUnion(bset1.Indices, bset2.Indices), SetIntersection(bset1.Indices, bset2.Indices));
476             auto xor2 = SetDifference(SetUnion(xor1, bset3.Indices), SetIntersection(xor1, bset3.Indices));
477             auto set_result = SetDifference(universum, xor2);
478             RC_ASSERT(result == set_result);
479         });
__anonea1bced32702(BSet &&bset1, BSet &&bset2, BSet &&bset3) 480         prop("lazy_and_not_then_indices_of<1>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
481             stat(bset1);
482             stat(bset2);
483             stat(bset3);
484             auto result =
485                 ContainerOf<StdSet>(BitVector::lazy_and_not_then_indices_of<1>(bset1.Bits, bset2.Bits, bset3.Bits));
486             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
487             auto universum = Universum(size);
488             auto set_and = SetIntersection(bset1.Indices, bset2.Indices);
489             auto set_not = SetDifference(universum, bset3.Indices);
490             auto set_result = SetIntersection(set_and, set_not);
491             RC_ASSERT(result == set_result);
492         });
__anonea1bced32802(BSet &&bset1, BSet &&bset2, BSet &&bset3) 493         prop("lazy_and_not_then_indices_of<0>()", [](BSet &&bset1, BSet &&bset2, BSet &&bset3) {
494             stat(bset1);
495             stat(bset2);
496             stat(bset3);
497             auto result =
498                 ContainerOf<StdSet>(BitVector::lazy_and_not_then_indices_of<0>(bset1.Bits, bset2.Bits, bset3.Bits));
499             auto size = std::min(std::min(bset1.Bits.size(), bset2.Bits.size()), bset3.Bits.size());
500             auto universum = Universum(size);
501             auto set_and = SetIntersection(bset1.Indices, bset2.Indices);
502             auto set_not = SetDifference(universum, bset3.Indices);
503             auto set_result = SetDifference(universum, SetIntersection(set_and, set_not));
504             RC_ASSERT(result == set_result);
505         });
506     }
507 }
508 
509 }  // namespace panda::verifier::test
510 
511 #endif  // !PANDA_CATCH2
512