| 55 | } |
| 56 | |
| 57 | void TestOneCase( |
| 58 | const NCB::TArraySubset<TVector<int>>& arraySubset, |
| 59 | const TVector<int>& expectedSubset |
| 60 | ) { |
| 61 | UNIT_ASSERT_EQUAL(arraySubset.Size(), expectedSubset.size()); |
| 62 | |
| 63 | // ForEach |
| 64 | { |
| 65 | size_t expectedIndex = 0; |
| 66 | arraySubset.ForEach([&](size_t index, int value) { |
| 67 | UNIT_ASSERT_VALUES_EQUAL(expectedIndex, index); |
| 68 | UNIT_ASSERT_VALUES_EQUAL(expectedSubset[index], value); |
| 69 | ++expectedIndex; |
| 70 | }); |
| 71 | UNIT_ASSERT_VALUES_EQUAL(expectedIndex, expectedSubset.size()); |
| 72 | } |
| 73 | |
| 74 | // ParallelForEach |
| 75 | { |
| 76 | NPar::TLocalExecutor localExecutor; |
| 77 | localExecutor.RunAdditionalThreads(3); |
| 78 | |
| 79 | for (size_t approximateBlockSize : xrange(0, 12)) { // use 0 as undefined |
| 80 | TVector<bool> indicesIterated(expectedSubset.size(), false); |
| 81 | arraySubset.ParallelForEach( |
| 82 | [&](size_t index, int value) { |
| 83 | UNIT_ASSERT_VALUES_EQUAL(expectedSubset[index], value); |
| 84 | |
| 85 | auto& indexIterated = indicesIterated.at(index); |
| 86 | UNIT_ASSERT(!indexIterated); // each index must be visited only once |
| 87 | indexIterated = true; |
| 88 | }, |
| 89 | &localExecutor, |
| 90 | approximateBlockSize != 0 ? TMaybe<size_t>(approximateBlockSize) : Nothing() |
| 91 | ); |
| 92 | UNIT_ASSERT(!IsIn(indicesIterated, false)); // each index was visited |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | // external iteration |
| 97 | { |
| 98 | auto* src = arraySubset.GetSrc(); |
| 99 | const auto* subsetIndexing = arraySubset.GetSubsetIndexing(); |
| 100 | |
| 101 | for (size_t approximateBlockSize : xrange(1, 12)) { |
| 102 | const NCB::TSimpleIndexRangesGenerator<size_t> parallelUnitRanges = |
| 103 | subsetIndexing->GetParallelUnitRanges(approximateBlockSize); |
| 104 | |
| 105 | TVector<bool> indicesIterated(expectedSubset.size(), false); |
| 106 | |
| 107 | for (size_t unitRangeIdx : xrange(parallelUnitRanges.RangesCount())) { |
| 108 | auto unitRange = parallelUnitRanges.GetRange(unitRangeIdx); |
| 109 | auto elementRange = subsetIndexing->GetElementRangeFromUnitRange(unitRange); |
| 110 | |
| 111 | size_t expectedIndex = elementRange.Begin; |
| 112 | subsetIndexing->ForEachInSubRange( |
| 113 | unitRange, |
| 114 | [&](size_t index, size_t srcIndex) { |
no test coverage detected