rexylib/include/rexy/detail/algorithm.hpp

87 lines
2.1 KiB
C++

#ifndef REXY_DETAIL_ALGORITHM_HPP
#define REXY_DETAIL_ALGORITHM_HPP
#include "../utility.hpp" //swap
#include <type_traits> //nothrow_invocable
#include <functional> //less, greater
#include <utility> //pair
#include <iterator> //iterator_traits
#include <cstdlib> //size_t
namespace rexy::detail{
template<class Iter, class Compare>
constexpr Iter qs_partition(Iter left, Iter right, const Compare& cmp)
noexcept(std::is_nothrow_invocable<Compare,decltype(*left),decltype(*right)>::value &&
noexcept(swap(*left,*right)))
{
auto range = right - left;
auto pivot = left + (range / 2);
auto value = *pivot;
//move pivot value all the way to the right side to preserve it
swap(*pivot, *right);
for(auto it = left;it != right;++it){
if(cmp(*it, value)){
swap(*left, *it);
++left;
}
}
//move pivot value back to proper position
swap(*left, *right);
return left;
}
template<class Iter, class Op>
constexpr std::pair<size_t,size_t> max_suffix(const Iter& needle, size_t nlen, const Op& op = Op()){
using value_type = typename std::iterator_traits<Iter>::value_type;
size_t max_suffix = -1;
size_t j = 0;
size_t k = 1;
size_t period = 1;
value_type a;
value_type b;
while(j + k < nlen){
a = needle[j + k];
b = needle[max_suffix + k];
if(op(a, b)){
j += k;
k = 1;
period = j - max_suffix;
}else if(a == b){
if(k != period){
++k;
}else{
j += period;
k = 1;
}
}else{
max_suffix = j++;
k = period = 1;
}
}
return {max_suffix, period};
}
template<class Iter>
constexpr std::pair<size_t,size_t> critical_factorization(const Iter& nstart, const Iter& nend){
auto msuffix = max_suffix(nstart, nend - nstart, std::less{});
auto msuffix_rev = max_suffix(nstart, nend - nstart, std::greater{});
if(msuffix.first < msuffix_rev.first){
return msuffix_rev;
}
return msuffix;
}
template<class Iter>
constexpr bool iter_compare(const Iter& left, const Iter& right, size_t length){
for(size_t i = 0;i < length;++i){
if(left[i] != right[i])
return false;
}
return true;
}
}
#endif