/** 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 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef REXY_DETAIL_ALGORITHM_HPP #define REXY_DETAIL_ALGORITHM_HPP #include "../utility.hpp" //swap #include //nothrow_invocable #include //pair, forward #include //iterator_traits #include //size_t namespace rexy::detail{ template constexpr Iter qs_partition(Iter left, Iter right, const Compare& cmp) noexcept(std::is_nothrow_invocable::value && noexcept(::rexy::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 ::rexy::swap(*pivot, *right); for(auto it = left;it != right;++it){ if(cmp(*it, value)){ ::rexy::swap(*left, *it); ++left; } } //move pivot value back to proper position ::rexy::swap(*left, *right); return left; } template constexpr std::pair max_suffix(const Iter& needle, std::size_t nlen, const Op& op = Op()){ using value_type = typename std::iterator_traits::value_type; std::size_t max_suffix = -1; std::size_t j = 0; std::size_t k = 1; std::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 constexpr std::pair critical_factorization(const Iter& nstart, const Iter& nend){ auto msuffix = max_suffix(nstart, nend - nstart, [](T&& left, U&& right) constexpr{ return std::forward(left) < std::forward(right); }); auto msuffix_rev = max_suffix(nstart, nend - nstart, [](T&& left, U&& right) constexpr{ return std::forward(left) > std::forward(right); }); if(msuffix.first < msuffix_rev.first){ return msuffix_rev; } return msuffix; } template constexpr bool iter_compare(const Iter& left, const Iter& right, std::size_t length){ for(std::size_t i = 0;i < length;++i){ if(left[i] != right[i]) return false; } return true; } } #endif