Files
piphoto/minimum.h

50 lines
1.4 KiB
C
Raw Normal View History

2017-08-10 13:51:39 -07:00
#pragma once
template <typename I, typename O>
struct Range {
I start;
I end;
I testpoint;
O testpoint_value;
};
// Find the minimum value of a callback within a range, using a given
// parallelism.
//
// Deterministic for a given parallelism, but not guaranteed to be correct.
// Since it does a non-exhaustive search, can be fooled by distributions with
// multiple peaks, especially those with the minimum in a narrow valley and
// other wider valleys.
2017-08-12 07:38:18 -07:00
template <typename I, typename O, int32_t P>
2017-08-10 13:51:39 -07:00
I FindPossibleMinimum(I min, I max, std::function<O(I)> callback) {
if (min == max) {
return min;
}
2017-08-12 11:46:05 -07:00
Array<Range<I, O>, P> ranges;
2017-08-10 13:51:39 -07:00
const I step = ((max - min) / P) + 1;
const I offset = step / 2;
2017-08-12 11:46:05 -07:00
for (int32_t i = 0; i < P; ++i) {
2017-08-12 07:38:18 -07:00
auto& range = ranges.at(i);
2017-08-12 11:46:05 -07:00
range.start = std::min(max, min + i * step);
2017-08-10 13:51:39 -07:00
range.end = std::min(max, range.start + (step - 1));
range.testpoint = range.start + offset;
}
// TODO: threads
for (auto& range : ranges) {
range.testpoint_value = callback(range.testpoint);
}
const auto& min_range = *std::min_element(ranges.begin(), ranges.end(), [](const Range<I, O>& a, const Range<I, O>& b) {
return a.testpoint_value < b.testpoint_value;
});
if (step == 1) {
return min_range.testpoint;
} else {
return FindPossibleMinimum<I, O, P>(min_range.start, min_range.end, callback);
}
}