This documentation is automatically generated by online-judge-tools/verification-helper
#include "src/opt/ternary_search.hpp"
#pragma once
/**
* @file ternary_search.hpp
* @brief Ternary Search
*/
#include <cassert>
#include <type_traits>
namespace workspace {
/**
* @brief Ternary search on discrete range.
* @param first Left end, inclusive
* @param last Right end, exclusive
* @param comp Compare function
* @return Local minimal point.
*/
template <class Iter, class Comp>
typename std::enable_if<
std::is_convertible<decltype(std::declval<Comp>()(std::declval<Iter>(),
std::declval<Iter>())),
bool>::value,
Iter>::type
ternary_search(Iter first, Iter last, Comp comp) {
assert(first < last);
typename std::make_signed<decltype(last - first)>::type dist(last - first);
while (2 < dist) {
Iter left(first + dist / 3), right(first + dist * 2 / 3);
if (comp(left, right))
last = right, dist = (dist + dist) / 3;
else
first = left, dist -= dist / 3;
}
if (1 < dist && comp(first + 1, first)) ++first;
return first;
}
/**
* @brief Ternary search on discrete range.
* @param first Left end, inclusive
* @param last Right end, exclusive
* @param func Function
* @return Local minimal point.
*/
template <class Iter, class Func>
typename std::enable_if<
std::is_same<decltype(std::declval<Func>()(std::declval<Iter>()), nullptr),
std::nullptr_t>::value,
Iter>::type
ternary_search(Iter const &first, Iter const &last, Func func) {
return ternary_search(first, last, [&](Iter const &__i, Iter const &__j) {
return func(__i) < func(__j);
});
}
/**
* @brief Ternary search on the real number line.
* @param first Left end
* @param last Right end
* @param eps Error tolerance
* @param comp Compare function
* @return Local minimal point.
*/
template <class Real, class Comp>
typename std::enable_if<
std::is_convertible<decltype(std::declval<Comp>()(std::declval<Real>(),
std::declval<Real>())),
bool>::value,
Real>::type
ternary_search(Real first, Real last, Real const &eps, Comp comp) {
assert(first < last);
while (eps < last - first) {
Real left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
if (comp(left, right))
last = right;
else
first = left;
}
return first;
}
/**
* @brief Ternary search on the real number line.
* @param first Left end
* @param last Right end
* @param eps Error tolerance
* @param func Function
* @return Local minimal point.
*/
template <class Real, class Func>
typename std::enable_if<
std::is_same<decltype(std::declval<Func>()(std::declval<Real>()), nullptr),
std::nullptr_t>::value,
Real>::type
ternary_search(Real const &first, Real const &last, Real const &eps,
Func func) {
return ternary_search(
first, last, eps,
[&](Real const &__i, Real const &__j) { return func(__i) < func(__j); });
}
} // namespace workspace
#line 2 "src/opt/ternary_search.hpp"
/**
* @file ternary_search.hpp
* @brief Ternary Search
*/
#include <cassert>
#include <type_traits>
namespace workspace {
/**
* @brief Ternary search on discrete range.
* @param first Left end, inclusive
* @param last Right end, exclusive
* @param comp Compare function
* @return Local minimal point.
*/
template <class Iter, class Comp>
typename std::enable_if<
std::is_convertible<decltype(std::declval<Comp>()(std::declval<Iter>(),
std::declval<Iter>())),
bool>::value,
Iter>::type
ternary_search(Iter first, Iter last, Comp comp) {
assert(first < last);
typename std::make_signed<decltype(last - first)>::type dist(last - first);
while (2 < dist) {
Iter left(first + dist / 3), right(first + dist * 2 / 3);
if (comp(left, right))
last = right, dist = (dist + dist) / 3;
else
first = left, dist -= dist / 3;
}
if (1 < dist && comp(first + 1, first)) ++first;
return first;
}
/**
* @brief Ternary search on discrete range.
* @param first Left end, inclusive
* @param last Right end, exclusive
* @param func Function
* @return Local minimal point.
*/
template <class Iter, class Func>
typename std::enable_if<
std::is_same<decltype(std::declval<Func>()(std::declval<Iter>()), nullptr),
std::nullptr_t>::value,
Iter>::type
ternary_search(Iter const &first, Iter const &last, Func func) {
return ternary_search(first, last, [&](Iter const &__i, Iter const &__j) {
return func(__i) < func(__j);
});
}
/**
* @brief Ternary search on the real number line.
* @param first Left end
* @param last Right end
* @param eps Error tolerance
* @param comp Compare function
* @return Local minimal point.
*/
template <class Real, class Comp>
typename std::enable_if<
std::is_convertible<decltype(std::declval<Comp>()(std::declval<Real>(),
std::declval<Real>())),
bool>::value,
Real>::type
ternary_search(Real first, Real last, Real const &eps, Comp comp) {
assert(first < last);
while (eps < last - first) {
Real left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
if (comp(left, right))
last = right;
else
first = left;
}
return first;
}
/**
* @brief Ternary search on the real number line.
* @param first Left end
* @param last Right end
* @param eps Error tolerance
* @param func Function
* @return Local minimal point.
*/
template <class Real, class Func>
typename std::enable_if<
std::is_same<decltype(std::declval<Func>()(std::declval<Real>()), nullptr),
std::nullptr_t>::value,
Real>::type
ternary_search(Real const &first, Real const &last, Real const &eps,
Func func) {
return ternary_search(
first, last, eps,
[&](Real const &__i, Real const &__j) { return func(__i) < func(__j); });
}
} // namespace workspace