rexylib/include/rexy/detail/algorithm.hpp
2020-09-19 10:42:45 -07:00

105 lines
2.8 KiB
C++

/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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