You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
2.5 KiB
68 lines
2.5 KiB
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <vector>
|
|
#include <functional>
|
|
|
|
namespace storm {
|
|
namespace utility {
|
|
namespace combinatorics {
|
|
|
|
template<typename IteratorType>
|
|
void forEach(std::vector<IteratorType> const& its, std::vector<IteratorType> const& ites, std::function<void (uint64_t, decltype(*std::declval<IteratorType>()))> const& setValueCallback, std::function<bool()> const& newCombinationCallback) {
|
|
typedef decltype((*std::declval<IteratorType>())) value_type;
|
|
STORM_LOG_ASSERT(its.size() == ites.size(), "Iterator begin/end mismatch.");
|
|
|
|
if (its.size() == 0) {
|
|
return;
|
|
}
|
|
|
|
bool allNonEmpty = true;
|
|
for (uint64_t index = 0; index < its.size(); ++index) {
|
|
if (its[index] == ites[index]) {
|
|
allNonEmpty = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!allNonEmpty) {
|
|
return;
|
|
}
|
|
|
|
std::vector<IteratorType> currentIterators(its);
|
|
|
|
// Fill the initial combination.
|
|
for (uint64_t index = 0; index < currentIterators.size(); ++index) {
|
|
setValueCallback(index, *currentIterators[index]);
|
|
}
|
|
|
|
// Enumerate all combinations until the callback yields false (or there are no more combinations).
|
|
while (true) {
|
|
bool cont = newCombinationCallback();
|
|
if (!cont) {
|
|
break;
|
|
}
|
|
|
|
uint64_t index = 0;
|
|
for (; index < currentIterators.size(); ++index) {
|
|
++currentIterators[index];
|
|
if (currentIterators[index] == ites[index]) {
|
|
currentIterators[index] = its[index];
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we are at the end, leave the loop.
|
|
if (index == currentIterators.size()) {
|
|
break;
|
|
} else {
|
|
for (uint64_t j = 0; j <= index; ++j) {
|
|
setValueCallback(j, *currentIterators[index]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|