From 74a4e4fb2eaf57a25c3c45efb10f3fc1843b718f Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Tue, 27 Nov 2018 10:00:36 +0000 Subject: [PATCH 01/60] First import of ScapegoatTree classes from old DuckLib/DuckMem. --- include/duckhandy/ScapegoatMap.hpp | 34 ++ include/duckhandy/ScapegoatMap.inl | 47 ++ include/duckhandy/ScapegoatTree.hpp | 131 ++++++ include/duckhandy/ScapegoatTree.inl | 686 ++++++++++++++++++++++++++++ 4 files changed, 898 insertions(+) create mode 100644 include/duckhandy/ScapegoatMap.hpp create mode 100644 include/duckhandy/ScapegoatMap.inl create mode 100644 include/duckhandy/ScapegoatTree.hpp create mode 100644 include/duckhandy/ScapegoatTree.inl diff --git a/include/duckhandy/ScapegoatMap.hpp b/include/duckhandy/ScapegoatMap.hpp new file mode 100644 index 0000000..dba3586 --- /dev/null +++ b/include/duckhandy/ScapegoatMap.hpp @@ -0,0 +1,34 @@ +#ifndef idDD2D1A57ABEB4BEEA0F7E46C347D1637 +#define idDD2D1A57ABEB4BEEA0F7E46C347D1637 + +#include "ScapegoatTree.hpp" + +namespace duckmem { + template + class ScapegoatMap { + public: + typedef K key_type; + typedef V value_type; + + ScapegoatMap ( void ); + ~ScapegoatMap ( void ); + + private: + class DerivedPair : public std::pair { + typedef std::pair parent_type; + public: + DerivedPair ( void ); + DerivedPair ( typename Loki::TypeTraits::ParameterType parKey, typename Loki::TypeTraits::ParameterType parValue ); + ~DerivedPair ( void ); + + bool operator< ( const DerivedPair& parOther ) const; + bool operator== ( const DerivedPair& parOther ) const; + }; + + ScapegoatTree m_tree; + }; +} //namespace duckmem + +#include "ScapegoatMap.inl" + +#endif diff --git a/include/duckhandy/ScapegoatMap.inl b/include/duckhandy/ScapegoatMap.inl new file mode 100644 index 0000000..971668c --- /dev/null +++ b/include/duckhandy/ScapegoatMap.inl @@ -0,0 +1,47 @@ +namespace duckmem { + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + ScapegoatMap::DerivedPair::DerivedPair() { + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + ScapegoatMap::DerivedPair::DerivedPair (typename Loki::TypeTraits::ParameterType parKey, typename Loki::TypeTraits::ParameterType parValue) : + parent_type(parKey, parValue) + { + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + ScapegoatMap::DerivedPair::~DerivedPair() { + } + + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- +// template +// bool ScapegoatMap::DerivedPair::operator< (const DerivedPair& parOther) const { +// const typename Hasher::HashType thisHash = Hasher::ComputeFullHash(this->first); +// const typename Hasher::HashType otherHash = Hasher::ComputeFullHash(parOther->first); +// if (thisHash == otherHash) { +// const bool typeMinor = (this->first < parOther.first); +// +// else +//wrong - this breaks total ordering condition return (thisHash < otherHash); +// } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + bool ScapegoatMap::DerivedPair::operator== (const DerivedPair& parOther) const { + const typename Hasher::HashType thisHash = Hasher::ComputeFullHash(this->first); + const typename Hasher::HashType otherHash = Hasher::ComputeFullHash(parOther->first); + if (thisHash != otherHash) + return false; + else + return (this->first == parOther.first); + } +} //namespace duckmem diff --git a/include/duckhandy/ScapegoatTree.hpp b/include/duckhandy/ScapegoatTree.hpp new file mode 100644 index 0000000..6fb085e --- /dev/null +++ b/include/duckhandy/ScapegoatTree.hpp @@ -0,0 +1,131 @@ +#ifndef id79CEDB2530B54204A6BEDCBE0B767EA1 +#define id79CEDB2530B54204A6BEDCBE0B767EA1 + +#include "TreeIterator.hpp" +#include "IteratorOnPtr.hpp" +#include "SmallObject.hpp" +#include "DuckMaths/Functions.hpp" +#include "DuckCore/Helpers.hpp" +#include "DuckCore/foreach.hpp" +#include "DuckCore/Casts.hpp" +#include +#include +#include + +//#define SCAPEGOATTREE_VERBOSE +//#define SCAPEGOATTREE_PARANOID + +#define SCAPEGOATTREE_DYNAMIC_SIZE_TYPE + +#if defined(DUCK_FINAL) +# if defined(SCAPEGOATTREE_VERBOSE) +# undef(SCAPEGOATTREE_VERBOSE) +# endif +#endif +#if !defined(ASSERTIONSENABLED) +# if defined(SCAPEGOATTREE_PARANOID) +# undef(SCAPEGOATTREE_PARANOID) +# endif +#endif + +namespace duckmem { +#if defined(WITH_DEBUG_TESTS) + bool RunScapegoatTests ( void ); +#endif + + template + class ScapegoatTree { + public: + typedef K value_type; + typedef size_t size_type; + + private: + template + struct TreeNodeStruct : public SmallObject { + typedef SizeType size_type; + TreeNodeStruct ( void ); + TreeNodeStruct ( typename Loki::TypeTraits::ParameterType parContent ) : content(parContent) {} + + K content; + TreeNodeStruct* left; + TreeNodeStruct* right; + size_type size; + }; +#if defined(SCAPEGOATTREE_DYNAMIC_SIZE_TYPE) + typedef typename duckcore::Iif) == sizeof(TreeNodeStruct), size_type, u32>::Result TreeNodeSizeType; + typedef TreeNodeStruct TreeNode; +#else + typedef TreeNodeStruct TreeNode; +#endif + + STATIC_ASSERT(sizeof(typename TreeNode::size_type) <= sizeof(size_type)); + typedef TreeNode NodeType; + typedef std::vector NodeStack; + typedef std::pair NodeTypePair; + + public: + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type* const_pointer; + typedef const value_type& const_reference; + typedef TreeIterator iterator; + typedef TreeIterator const_iterator; + + ScapegoatTree ( void ); + explicit ScapegoatTree ( float parAlpha ); + ~ScapegoatTree ( void ); + + float GetAlpha ( void ) const { return m_alpha; } + bool Include ( typename Loki::TypeTraits::ParameterType parSearch ) const; + std::pair insert ( typename Loki::TypeTraits::ParameterType parKey ); + iterator insert ( const iterator&, typename Loki::TypeTraits::ParameterType parValue ); + bool empty ( void ) const { return m_count == 0; } + size_type size ( void ) const { return m_count; } + void reserve ( size_type parSize ) { m_reserved = std::max(parSize, m_count); } + size_type capacity ( void ) const { return m_reserved; } + void clear ( void ); + void erase ( iterator parItem ); + void erase ( iterator parFrom, iterator parLast ); + size_type erase ( typename Loki::TypeTraits::ParameterType parKey ); + + iterator begin ( void ); + const_iterator begin ( void ) const; + iterator end ( void ) { return iterator(); } + const_iterator end ( void ) const { return const_iterator(); } + + private: + template + static T* FindClosestMatch ( T* parTree, typename Loki::TypeTraits::ParameterType parKey ); + static NodeType* GetInsertParent ( NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey, NodeStack& parRewind ); + static NodeType* FindIFP ( const NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey ); + static NodeType* FindParentIFP ( NodeType* parTree, const NodeType* parSearchNodeAddr ); + static NodeType* GetNewNode ( typename Loki::TypeTraits::ParameterType parKey ); + static void DeleteNodes ( NodeType* parNode ); + bool IsAlphaHeightBalanced ( size_type parHeight, size_type parSize ) const pure_function; + NodeTypePair FindScapegoat ( NodeStack& parParents ) const; + static NodeType* Rebalance ( NodeType* parSubtree, size_type parDepthHint ); + static NodeType* Compress_first ( NodeType* parFrom, size_type parDepthHint ); + static NodeType* Compress ( NodeType* parFrom ); + static size_type GetMaxBalancedDepth ( size_type parSize, float parAlphaInvLogInv ) pure_function; + static size_type GetTreeMinDepthIB ( size_type parSize, float parAlphaInvLogInv ) pure_function; + static NodeType* DetachBottomNode ( NodeType* parTree, bool parSuccessor ); + void RebalanceAfterDeletionIFN ( void ); + +#if defined(SCAPEGOATTREE_PARANOID) + static size_type AssertNodeSize ( const NodeType* parSubtree ); + static size_type FindMaxDepth ( const NodeType* parSubtree ) { return FindMaxDepth_rec(parSubtree) - 1; } + static size_type FindMaxDepth_rec ( const NodeType* parSubtree ); +#endif + + NodeType* m_root; + size_type m_count; + size_type m_countMax; + size_type m_reserved; + float m_alpha; + float m_alphainvloginv; + }; +} //namespace duckmem + +#include "ScapegoatTree.inl" + +#endif diff --git a/include/duckhandy/ScapegoatTree.inl b/include/duckhandy/ScapegoatTree.inl new file mode 100644 index 0000000..946bfd6 --- /dev/null +++ b/include/duckhandy/ScapegoatTree.inl @@ -0,0 +1,686 @@ +namespace duckmem { + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + ScapegoatTree::ScapegoatTree() : + m_root(NULL), + m_count(0), + m_countMax(0), + m_reserved(0), + m_alpha(0.6f) + { + m_alphainvloginv = 1.0f / std::log(1.0f / m_alpha); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + ScapegoatTree::ScapegoatTree (float parAlpha) : + m_root(NULL), + m_count(0), + m_countMax(0), + m_reserved(0), + m_alpha(parAlpha) + { + Assert(parAlpha < 1.0f); + Assert(parAlpha >= 0.5f); + m_alphainvloginv = 1.0f / std::log(1.0f / m_alpha); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + ScapegoatTree::~ScapegoatTree() { + DeleteNodes(m_root); +#if defined(DUCK_DEBUG) + m_root = NULL; + m_count = 0xDEADBEEF; + m_countMax = 0xDEADBEEF; + m_reserved = 0xDEADBEEF; +#endif + } + + ///------------------------------------------------------------------------- + ///I can't really find a good optimization for this method, so I'll just + ///ignore the hint and rely on the normal insert(). + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::iterator ScapegoatTree::insert (const iterator&, typename Loki::TypeTraits::ParameterType parValue) { + std::pair retVal = insert(parValue); + return retVal.first; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + std::pair::iterator, bool> ScapegoatTree::insert (typename Loki::TypeTraits::ParameterType parKey) { + const size_type depthHint = GetMaxBalancedDepth(std::max(m_reserved, m_count + 1), m_alphainvloginv) + 3; +#if defined(SCAPEGOATTREE_VERBOSE) + std::cout << "insert(): depthHint = " << depthHint << ", m_count = " << m_count << ", m_countMax = " << m_countMax << ", m_reserved = " << m_reserved << std::endl; +#endif + if (NULL == m_root) { + m_root = GetNewNode(parKey); + m_root->left = m_root->right = NULL; + m_root->size = 1; + m_count = 1; + m_countMax = 1; + m_reserved = std::max(m_count, m_reserved); + + IteratorOnPtr rootWrapper(&m_root, 1); + return std::pair(iterator(rootWrapper, 1, depthHint), true); + } + else { + //Refuse to add a new item if the tree has more items than it + //can count + if (std::numeric_limits::max() == m_count or std::numeric_limits::max() == m_root->size) { + AssertNotReached(); + return std::pair(end(), false); + } + + NodeStack stack; + stack.reserve(depthHint); + NodeType* const closestMatch = GetInsertParent(m_root, parKey, stack); + Assert(stack.size() <= depthHint); + if (closestMatch->content == parKey) + return std::pair(iterator(stack.begin(), stack.size(), depthHint), false); + Assert(NULL == closestMatch->left or closestMatch->left->content < parKey); + Assert(NULL == closestMatch->right or parKey < closestMatch->right->content); + NodeType* const newNode = GetNewNode(parKey); + newNode->left = newNode->right = NULL; + newNode->size = 1; + if (parKey < closestMatch->content) { + Assert(NULL == closestMatch->left); + closestMatch->left = newNode; + } + else { + Assert(NULL == closestMatch->right); + closestMatch->right = newNode; + } + ++m_count; + m_countMax = std::max(m_count, m_countMax); + m_reserved = std::max(m_reserved, m_count); + + //Update the count of every node + foreach_tn (itNode, stack) { + ++(*itNode)->size; + } + + //Add the new node to the stack + Assert(stack.capacity() > stack.size()); + stack.push_back(newNode); +#if defined(SCAPEGOATTREE_PARANOID) + const size_type totalSize = AssertNodeSize(m_root); + Assert(totalSize == m_count); + Assert(m_root->size == duckcore::checked_numcast(m_count)); +#endif + + size_type newNodeDepth = stack.size() - 1; + //Rebalance if necessary + if (not IsAlphaHeightBalanced(newNodeDepth, this->size())) { +#if defined(SCAPEGOATTREE_PARANOID) + Assert(FindMaxDepth(m_root) == newNodeDepth); +#endif + Assert(GetMaxBalancedDepth(static_cast(m_root->size), m_alphainvloginv) + 1 == newNodeDepth); + std::pair scapegoatAndParent = FindScapegoat(stack); + AssertRelease(NULL != scapegoatAndParent.first); + NodeType* const newRoot = Rebalance(scapegoatAndParent.first, newNodeDepth + 1); + NodeType* const parent = scapegoatAndParent.second; + if (parent == NULL) { + Assert(scapegoatAndParent.first == m_root); + m_root = newRoot; + m_countMax = m_count; + } + else { + Assert(newRoot != parent); + if (parent->left == scapegoatAndParent.first) { + parent->left = newRoot; + } + else { + Assert(parent->right == scapegoatAndParent.first); + parent->right = newRoot; + } + } +#if defined(SCAPEGOATTREE_PARANOID) + AssertNodeSize(m_root); + Assert(FindMaxDepth(m_root) <= GetMaxBalancedDepth(static_cast(m_root->size), m_alphainvloginv)); +#endif + //Rebuild the stack. + //TODO: this is ugly and slow, see if you can find a better way + stack.clear(); + GetInsertParent(m_root, parKey, stack); + newNodeDepth = stack.size() - 1; + Assert(IsAlphaHeightBalanced(newNodeDepth, this->size())); + } + return std::pair(iterator(stack.begin(), newNodeDepth + 1, duckmath::log2_fast(m_reserved + 1)), true); + } + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::Rebalance (NodeType* parSubtree, size_type parDepthHint) { +#if defined(SCAPEGOATTREE_VERBOSE) + std::cout << "Rebalancing subtree" << std::endl; +#endif + Assert(NULL != parSubtree); + NodeType* const newRoot = Compress_first(parSubtree, parDepthHint); + NodeType* const retVal = Compress(newRoot); + return retVal; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeTypePair ScapegoatTree::FindScapegoat (NodeStack& parParents) const { + Assert(not parParents.empty()); + const size_type height = parParents.size(); + for (size_type z = parParents.size() - 1; z > 0; --z) { + NodeType& currNode = *(parParents[z - 1]); + Assert(height - z > 0); + if (not IsAlphaHeightBalanced(height - z, static_cast(currNode.size))) { + NodeType* parent; + if (z == 1) + parent = NULL; + else + parent = parParents[z - 2]; + return NodeTypePair(&currNode, parent); + } + } + AssertNotReached(); + set_not_reached(); + return NodeTypePair(NULL, NULL); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::GetNewNode (typename Loki::TypeTraits::ParameterType parKey) { + return new NodeType(parKey); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + template + T* ScapegoatTree::FindClosestMatch (T* parTree, typename Loki::TypeTraits::ParameterType parKey) { + Assert(NULL != parTree); + //if (parTree->left and parKey <= parTree->left->content) + if (parTree->left and not (parTree->left->content < parKey)) + return FindClosestMatch(parTree->left, parKey); + //else if (parTree->right and parKey >= parTree->right->content) + else if (parTree->right and not (parKey < parTree->right->content)) + return FindClosestMatch(parTree->right, parKey); + else + return parTree; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::GetInsertParent (NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey, NodeStack& parRewind) { + Assert(NULL != parTree); + NodeType* retVal = parTree; + bool goLeft; + while ((goLeft = (retVal->left and parKey < retVal->content)) or (retVal->right and retVal->content < parKey)) { + parRewind.push_back(retVal); + if (goLeft) { + Assert(NULL != retVal->left); + Assert(parKey < retVal->content); + retVal = retVal->left; + } + else { + Assert(NULL != retVal->right); + Assert(retVal->content < parKey); + retVal = retVal->right; + } + } + Assert(NULL != retVal); + Assert(parRewind.empty() or parRewind.back() != retVal); + parRewind.push_back(retVal); + return retVal; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + void ScapegoatTree::DeleteNodes (NodeType* parNode) { + if (parNode) { + DeleteNodes(parNode->left); + DeleteNodes(parNode->right); + delete parNode; + } + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + bool ScapegoatTree::IsAlphaHeightBalanced (size_type parHeight, size_type parSize) const { + const float sz = static_cast(parSize); + const float ha = std::floor(std::log(sz) * m_alphainvloginv); + const float height = static_cast(parHeight); + return height <= ha; + } + + ///------------------------------------------------------------------------- + ///Stout/Warren vine to tree. + ///This function destroys the links of the given subtree and creates a + ///structure that is suitable for Compress(). Input is treated as if it + ///was a linked list. + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::Compress_first (NodeType* parFrom, size_type parDepthHint) { + const size_type vineSize = static_cast(parFrom->size); + const size_type iteratorDepth = parDepthHint; +#if defined(SCAPEGOATTREE_VERBOSE) + std::cout << "Compress_first(): vineSize = " << vineSize << ", iteratorDepth = " << iteratorDepth << std::endl; +#endif + iterator itFirstStep(parFrom, iteratorDepth); + + struct DummyNode { + DummyNode ( void ) : right(NULL) {} + NodeType* right; + }; + class NodeWrapper { + public: + NodeWrapper ( void ) {} + explicit NodeWrapper ( NodeType* parOther ) : m_current(parOther), m_right(&parOther->right) {} + explicit NodeWrapper ( DummyNode* parOther ) : m_current(NULL), m_right(&parOther->right) {} + void Replace ( NodeType* parOther ) { m_current = parOther; m_right = &parOther->right; } + void Replace ( NodeWrapper* parOther ) { m_current = parOther->m_current; m_right = parOther->m_right; } + NodeType*& left ( void ) { Assert(m_current); return m_current->left; } + NodeType*& right ( void ) { Assert(m_right); return *m_right; } + typename NodeType::size_type& size ( void ) { Assert(m_current); return m_current->size; } + NodeType* pointer ( void ) { return m_current; } + private: + NodeType* m_current; + NodeType** m_right; + }; + + DummyNode pseudorootMem; + NodeWrapper parent(&pseudorootMem); + NodeWrapper current; + NodeWrapper child(&pseudorootMem); + + size_type iterationsCount; + if (duckcore::IsPowerOfTwo(vineSize + 1)) + iterationsCount = (1 << (duckmath::log2_fast(vineSize))) - 1; + else + iterationsCount = (vineSize - ((1 << duckmath::log2_fast(vineSize)) - 1)); + +#if defined(SCAPEGOATTREE_VERBOSE) + std::cout << "vineSize = " << vineSize << ", iterationsCount = " << iterationsCount << std::endl; +#endif + Assert(iterationsCount < vineSize); //Underflow error? + Assert(iterationsCount > 0); + for (size_type z = 0; z < iterationsCount; ++z) { + current.Replace(itFirstStep.GetPointer()); + ++itFirstStep; + child.Replace(itFirstStep.GetPointer()); + ++itFirstStep; + + current.left() = NULL; + current.right() = NULL; + current.size() = 1; + parent.right() = child.pointer(); + child.left() = current.pointer(); + Assert(z * 2 < vineSize); + child.size() = duckcore::checked_numcast(vineSize - z * 2); + Assert(child.size() >= 1); + + parent.Replace(&child); + } + + Assert(iterationsCount * 2 <= vineSize); + for (size_type z = iterationsCount * 2; z < vineSize; ++z) { + child.right() = itFirstStep.GetPointer(); + child.Replace(itFirstStep.GetPointer()); + ++itFirstStep; + child.left() = NULL; + child.size() = duckcore::checked_numcast(vineSize - z); + } + child.right() = NULL; + child.size() = (child.left() ? 2 : 1); + +#if defined(SCAPEGOATTREE_VERBOSE) + std::cout << "Original size was " << vineSize << ", root's size is " << pseudorootMem.right->size << std::endl; +#endif + Assert(vineSize == static_cast(pseudorootMem.right->size)); +#if defined(SCAPEGOATTREE_PARANOID) + AssertNodeSize(pseudorootMem.right); + Assert(FindMaxDepth(pseudorootMem.right) <= vineSize); +#endif + return pseudorootMem.right; + } + + ///------------------------------------------------------------------------- + ///Stout/Warren vine to tree. + ///Performs the second and subsequent steps for compressing. + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::Compress (NodeType* parFrom) { + Assert(NULL != parFrom); + //We don't know if the tree is complete, so let's calculate its depth + //rounded up to the nearest complete tree + const size_type treeSize = static_cast(parFrom->size); + const size_type m = duckmath::log2_fast(1 + treeSize); + const size_type treeHeight = duckmath::log2_fast(treeSize + (1 << m)); + +#if defined(SCAPEGOATTREE_PARANOID) + size_type maxDepthInTree = FindMaxDepth(parFrom); + { + //We know step 0 of compression has already been done, so on with + //the spine size at step 1 (the one we're willing to do) + const size_type vineSize = (1 << (treeHeight - 1)) - 1; + size_type count = 0; + NodeType* currNode = parFrom; + do { + ++count; + currNode = currNode->right; + } while (currNode); + const size_type countedNodes = ((count + 1) bitand ~1) - 1; +#if defined(SCAPEGOATTREE_VERBOSE) + std::cout << "treeSize = " << treeSize << ", vineSize = " << vineSize << ", treeHeight = " << treeHeight << ", manually counted " << countedNodes << " nodes (" << count << ")\n"; +#endif + Assert(duckcore::IsPowerOfTwo(countedNodes + 1)); + Assert(vineSize == countedNodes); + } +#endif + + NodeType* retVal = parFrom; + + Assert(treeHeight >= 2); + + for (size_type k = 1; k < treeHeight - 1; ++k) { +#if defined(SCAPEGOATTREE_VERBOSE) + std::cout << "Compress() step " << k << std::endl; +#endif + //The rebalanced tree takes treeHeight-1 steps. One step has been done + //already, so we perform the remaining treeHeight-2 steps. + NodeType* scanner; + NodeType* child = retVal; + retVal = child->right; + Assert(NULL != retVal); + + const size_type spineSize = (1 << (treeHeight - k - 1)) - 1; + Assert(spineSize > 0); + for (size_type s = 0; s < spineSize; ++s) { + scanner = child->right; + Assert(NULL != scanner); + child->right = scanner->left; + scanner->left = child; + + const typename NodeType::size_type leftBranchSize = (child->right ? child->right->size : 0); + + child->size -= scanner->size - leftBranchSize; + scanner->size += child->size - leftBranchSize; + + if (s + 1 < spineSize) { + child = scanner->right; + Assert(NULL != child); + scanner->right = child->right; + } + +#if defined(SCAPEGOATTREE_VERBOSE) + const size_type subtreeSize = (1 << (k + 1)) - 1; + std::cout << "k=" << k << " - Scanner's size updated to " << scanner->size << ", calculated subtreeSize = " << subtreeSize << std::endl; +#endif + } + Assert(NULL != scanner); + Assert(NULL != retVal); + Assert(treeSize == static_cast(retVal->size)); +#if defined(SCAPEGOATTREE_PARANOID) + AssertNodeSize(retVal); + { + const size_type newDepth = FindMaxDepth(retVal); + Assert(newDepth <= maxDepthInTree); + maxDepthInTree = newDepth; + } +#endif + } + + Assert(static_cast(retVal->size) == treeSize); + return retVal; + } + +#if defined(SCAPEGOATTREE_PARANOID) + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::size_type ScapegoatTree::AssertNodeSize (const NodeType* parSubtree) { + Assert(parSubtree); + + typename NodeType::size_type localSize = 1; + if (parSubtree->left) { + localSize += AssertNodeSize(parSubtree->left); + } + if (parSubtree->right) { + localSize += AssertNodeSize(parSubtree->right); + } + Assert(parSubtree->size == localSize); + return localSize; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::size_type ScapegoatTree::FindMaxDepth_rec (const NodeType* parSubtree) { + Assert(parSubtree); + typename NodeType::size_type depthLeft = 0; + typename NodeType::size_type depthRight = 0; + + if (parSubtree->left) { + depthLeft = FindMaxDepth_rec(parSubtree->left); + } + if (parSubtree->right) { + depthRight = FindMaxDepth_rec(parSubtree->right); + } + + return 1 + std::max(depthLeft, depthRight); + } +#endif + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::size_type ScapegoatTree::GetMaxBalancedDepth (size_type parSize, float parAlphaInvLogInv) { + const float ha = std::log(static_cast(parSize)) * parAlphaInvLogInv; + return static_cast(ha); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::iterator ScapegoatTree::begin() { + if (NULL == m_root) + return iterator(); + + const size_type depthHint = GetTreeMinDepthIB(m_reserved, m_alphainvloginv) + 1; +#if defined(SCAPEGOATTREE_PARANOID) + Assert(IsAlphaHeightBalanced(FindMaxDepth(m_root), static_cast(m_root->size))); + Assert(FindMaxDepth(m_root) + 1 <= depthHint); +#endif + return iterator(m_root, depthHint + 1); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::const_iterator ScapegoatTree::begin() const { + if (NULL == m_root) + return iterator(); + + const size_type depthHint = GetTreeMinDepthIB(m_count, m_alphainvloginv) + 1; +#if defined(SCAPEGOATTREE_PARANOID) + Assert(IsAlphaHeightBalanced(FindMaxDepth(m_root), static_cast(m_root->size))); + Assert(FindMaxDepth(m_root) + 1 <= depthHint); +#endif + return const_iterator(m_root, depthHint + 1); + } + + ///------------------------------------------------------------------------- + ///Get min tree depth if balanced + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::size_type ScapegoatTree::GetTreeMinDepthIB (size_type parSize, float parAlphaInvLogInv) { + const float sz = static_cast(parSize); + const size_type roundedDownDepthBase2 = duckmath::log2_fast(parSize + 1); + const float nodesAtLastLevel = (roundedDownDepthBase2 == 0 ? 0 : static_cast(1 << roundedDownDepthBase2) - 1.0f); + const float retVal = std::log(sz + nodesAtLastLevel) * parAlphaInvLogInv; + return static_cast(retVal); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + void ScapegoatTree::clear() { + DeleteNodes(m_root); + m_count = 0; + m_countMax = 0; + m_root = NULL; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::FindIFP (const NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey) { + while (parTree) { + if (parKey < parTree->content) + parTree = parTree->left; + else if (parTree->content < parKey) + parTree = parTree->right; + else + break; + } + return parTree; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::FindParentIFP (NodeType* parTree, const NodeType* parSearchNodeAddr) { + if (parTree == parSearchNodeAddr) + return NULL; + NodeType* parent = parTree; + while (parTree and (parTree->left != parSearchNodeAddr and parTree->right != parSearchNodeAddr)) { + if (parSearchNodeAddr->content < parTree->content) + parTree = parTree->left; + else if (parTree->content < parSearchNodeAddr->content) + parTree = parTree->right; + else + break; + parent = parTree; + } + return parent; + } + + ///------------------------------------------------------------------------- + ///Set parSuccessor to true to get the in-order successor, or false to + ///get the in-order predecessor. + ///------------------------------------------------------------------------- + template + typename ScapegoatTree::NodeType* ScapegoatTree::DetachBottomNode (NodeType* parTree, bool parSuccessor) { + AssertRelease(NULL != parTree); + AssertRelease(NULL != parTree->left and NULL != parTree->right); + if (parSuccessor) { + NodeType* inorderSuccessor = parTree->right; + NodeType* successorsParent = parTree; + while (NULL != inorderSuccessor->left) { + successorsParent = inorderSuccessor; + inorderSuccessor = inorderSuccessor->left; + } + Assert(inorderSuccessor == successorsParent->left and inorderSuccessor != successorsParent->right); + Assert(NULL == inorderSuccessor->left); + Assert(NULL == inorderSuccessor->right or inorderSuccessor->right->content < successorsParent->content); + successorsParent->left = inorderSuccessor->right; + Assert(inorderSuccessor); + return inorderSuccessor; + } + else { + NodeType* inorderPredecessor = parTree->left; + NodeType* predecessorsParent = parTree; + while (NULL != inorderPredecessor->right) { + predecessorsParent = inorderPredecessor; + inorderPredecessor = inorderPredecessor->right; + } + Assert(inorderPredecessor == predecessorsParent->right and inorderPredecessor != predecessorsParent->left); + Assert(NULL == inorderPredecessor->right); + Assert(NULL == inorderPredecessor->left or predecessorsParent->content < inorderPredecessor->left->content); + predecessorsParent->right = inorderPredecessor->left; + Assert(inorderPredecessor); + return inorderPredecessor; + } + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + bool ScapegoatTree::Include (typename Loki::TypeTraits::ParameterType parSearch) const { + const NodeType* const found = FindIFP(m_root, parSearch); + Assert(not found or not (parSearch < found->content or found->content < parSearch)); + return static_cast(NULL != found); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + void ScapegoatTree::RebalanceAfterDeletionIFN() { + const float sz = static_cast(m_count); + const float m = static_cast(m_countMax); + if (sz < m_alpha * m) { + const size_type sizeHint = static_cast(std::ceil(std::log(sz) * m_alphainvloginv)) + 1; + Rebalance(m_root, sizeHint); + m_countMax = m_count; + } + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + void ScapegoatTree::erase (iterator parItem) { + NodeType* const dele = parItem->GetPointer(); + AssertRelease(NULL != dele); + Assert(m_count > 0); + + NodeType* parent; + if (dele == m_root) + parent = m_root; + else + parent = FindParentIFP(m_root, dele); + Assert(NULL != parent); + + if (parent) { + Assert(dele == parent->left or dele == parent->right or dele == parent); + NodeType*& parentChildRef = (dele == m_root ? m_root : (dele == parent->left ? parent->left : parent->right)); + if (NULL == dele->left and NULL == dele->right) { + parentChildRef = NULL; + } + else if (NULL == dele->left xor NULL == dele->right) { + parentChildRef = (dele->left ? dele->left : dele->right); + } + else { + NodeType* const inorderSuccessor = DetachBottomNode(dele, true); + + parentChildRef = inorderSuccessor; + inorderSuccessor->left = dele->left; + inorderSuccessor->right = dele->right; + } + Assert(NULL == parent->left or parent->left->content < parent->content); + Assert(NULL == parent->right or parent->content < parent->right->content); + } + --m_count; + delete dele; + RebalanceAfterDeletionIFN(); + } + +// ///------------------------------------------------------------------------- +// ///------------------------------------------------------------------------- +// template +// void ScapegoatTree::erase (iterator parFrom, iterator parLast) { +// } +// +// ///------------------------------------------------------------------------- +// ///------------------------------------------------------------------------- +// template +// typename ScapegoatTree::size_type ScapegoatTree::erase (typename Loki::TypeTraits::ParameterType parKey) { +// } +} //namespace duckmem From f085f3c3d2a4cf62862d09e115e21ba407ed487c Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Tue, 27 Nov 2018 10:09:49 +0000 Subject: [PATCH 02/60] Rename to conform to duckhandy and add some of the missing files. --- .../scapegoat_map.inl} | 0 .../scapegoat_tree.inl} | 0 include/duckhandy/implem/tree_iterator.inl | 235 ++++++++++++++++++ .../{ScapegoatMap.hpp => scapegoat_map.hpp} | 4 +- .../{ScapegoatTree.hpp => scapegoat_tree.hpp} | 4 +- include/duckhandy/tree_iterator.hpp | 121 +++++++++ 6 files changed, 360 insertions(+), 4 deletions(-) rename include/duckhandy/{ScapegoatMap.inl => implem/scapegoat_map.inl} (100%) rename include/duckhandy/{ScapegoatTree.inl => implem/scapegoat_tree.inl} (100%) create mode 100644 include/duckhandy/implem/tree_iterator.inl rename include/duckhandy/{ScapegoatMap.hpp => scapegoat_map.hpp} (92%) rename include/duckhandy/{ScapegoatTree.hpp => scapegoat_tree.hpp} (98%) create mode 100644 include/duckhandy/tree_iterator.hpp diff --git a/include/duckhandy/ScapegoatMap.inl b/include/duckhandy/implem/scapegoat_map.inl similarity index 100% rename from include/duckhandy/ScapegoatMap.inl rename to include/duckhandy/implem/scapegoat_map.inl diff --git a/include/duckhandy/ScapegoatTree.inl b/include/duckhandy/implem/scapegoat_tree.inl similarity index 100% rename from include/duckhandy/ScapegoatTree.inl rename to include/duckhandy/implem/scapegoat_tree.inl diff --git a/include/duckhandy/implem/tree_iterator.inl b/include/duckhandy/implem/tree_iterator.inl new file mode 100644 index 0000000..09a296a --- /dev/null +++ b/include/duckhandy/implem/tree_iterator.inl @@ -0,0 +1,235 @@ +namespace duckmem { + namespace Implem { + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + bool TreeIterator_base

::Exhausted() const { + return m_stack.empty(); + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + TreeIterator_base

::TreeIterator_base (const TreeIterator_base& parOther) : + m_stack(parOther.m_stack) + { + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + template + TreeIterator_base

::TreeIterator_base (const TreeIterator_base& parOther) { + typename TreeIterator_base::StackType otherStackCopy(parOther.m_stack); + std::vector

localCopy; + localCopy.reserve(parOther.m_stack.size()); + while (not otherStackCopy.empty()) { + P convertedItem = otherStackCopy.top(); + localCopy.push_back(convertedItem); + otherStackCopy.pop(); + } + m_stack.reserve(parOther.m_stack.capacity()); + for (typename std::vector

::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) { + Assert(m_stack.capacity() > m_stack.size()); + m_stack.push(*itRev); + } + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + typename TreeIterator_const_layer::reference TreeIterator_const_layer::operator* () { + AssertRelease(not this->Exhausted()); + return this->m_stack.top()->content; + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + typename TreeIterator_const_layer::const_reference TreeIterator_const_layer::operator* () const { + AssertRelease(not this->Exhausted()); + return this->m_stack.top()->content; + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + typename TreeIterator_const_layer::pointer TreeIterator_const_layer::operator-> () { + AssertRelease(not this->Exhausted()); + return &this->m_stack.top()->content; + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + typename TreeIterator_const_layer::const_pointer TreeIterator_const_layer::operator-> () const { + AssertRelease(not this->Exhausted()); + return &this->m_stack.top()->content; + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + N* TreeIterator_const_layer::GetPointer() { + AssertRelease(not this->Exhausted()); + return this->m_stack.top(); + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + const N* TreeIterator_const_layer::GetPointer() const { + AssertRelease(not this->Exhausted()); + return this->m_stack.top(); + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + typename TreeIterator_const_layer::const_reference TreeIterator_const_layer::operator* () const { + AssertRelease(not this->Exhausted()); + return this->m_stack.top()->content; + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + typename TreeIterator_const_layer::const_pointer TreeIterator_const_layer::operator-> () const { + AssertRelease(not this->Exhausted()); + return &this->m_stack.top()->content; + } + + ///--------------------------------------------------------------------- + ///--------------------------------------------------------------------- + template + const N* TreeIterator_const_layer::GetPointer() const { + AssertRelease(not this->Exhausted()); + return this->m_stack.top(); + } + } //namespace Implem + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + TreeIterator::TreeIterator() { + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + TreeIterator::TreeIterator (const TreeIterator& parOther) : + parent_type(parOther) + { + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + template + TreeIterator::TreeIterator (const TreeIterator& parOther) : + parent_type(parOther) + { + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + template + TreeIterator::TreeIterator (S parCopyStackBottomUp, size_type parStackLen, size_type parMaxDepthHint) { + AssertRelease(parStackLen > 0); + this->m_stack.reserve(std::max(parStackLen, parMaxDepthHint)); + typename StackType::value_type prevNode = *parCopyStackBottomUp; + ++parCopyStackBottomUp; + this->m_stack.push(prevNode); + + for (size_type z = 1; z < parStackLen; ++z) { + typename StackType::value_type currNode = *parCopyStackBottomUp; + if (prevNode->left == currNode) { + Assert(this->m_stack.capacity() > this->m_stack.size()); + this->m_stack.push(currNode); + } + else { + //If you get this assertion make sure the iterator you are + //passing in is reversed (ie: from leaf to root) + AssertRelease(currNode == prevNode->right); + } + + prevNode = currNode; + ++parCopyStackBottomUp; + } + Assert(not this->Exhausted()); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + TreeIterator::TreeIterator (NodeTypePointer parRoot, size_type parMaxDepthHint) { + if (parMaxDepthHint > 0) + this->m_stack.reserve(parMaxDepthHint); + RecurseLeft(parRoot); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + TreeIterator::~TreeIterator() { + } + + ///------------------------------------------------------------------------- + ///Post-increment + ///------------------------------------------------------------------------- + template + TreeIterator TreeIterator::operator++ (int) { + AssertRelease(not this->Exhausted()); + TreeIterator retVal = *this; + ++(*this); + return retVal; + } + + ///------------------------------------------------------------------------- + ///Pre-increment + ///------------------------------------------------------------------------- + template + TreeIterator& TreeIterator::operator++() { + AssertRelease(not this->Exhausted()); + NodeTypePointer currNode = this->m_stack.top(); +#if defined(ASSERTIONSENABLED) + const size_type stackCapacity = this->m_stack.capacity(); +#endif + this->m_stack.pop(); +#if defined(ASSERTIONSENABLED) + //It shouldn't normally happen, but it's just to make sure + Assert(stackCapacity == this->m_stack.capacity()); +#endif + RecurseLeft(currNode->right); + return *this; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + const TreeIterator& TreeIterator::operator= (const TreeIterator& parOther) { + this->m_stack = parOther.m_stack; + Assert(this->m_stack.capacity() >= parOther.m_stack.capacity()); + return *this; + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + bool TreeIterator::operator== (const TreeIterator& parOther) const { + return this->m_stack.size() == parOther.m_stack.size() and (this->m_stack.empty() or parOther.m_stack.top() == this->m_stack.top()); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + void TreeIterator::RecurseLeft (NodeTypePointer parFrom) { + NodeTypePointer currNode = parFrom; + while (NULL != currNode) { + Assert(this->m_stack.capacity() > this->m_stack.size()); + this->m_stack.push(currNode); + currNode = currNode->left; + } + } +} //namespace duckmem diff --git a/include/duckhandy/ScapegoatMap.hpp b/include/duckhandy/scapegoat_map.hpp similarity index 92% rename from include/duckhandy/ScapegoatMap.hpp rename to include/duckhandy/scapegoat_map.hpp index dba3586..e0010fa 100644 --- a/include/duckhandy/ScapegoatMap.hpp +++ b/include/duckhandy/scapegoat_map.hpp @@ -1,7 +1,7 @@ #ifndef idDD2D1A57ABEB4BEEA0F7E46C347D1637 #define idDD2D1A57ABEB4BEEA0F7E46C347D1637 -#include "ScapegoatTree.hpp" +#include "scapegoat_tree.hpp" namespace duckmem { template @@ -29,6 +29,6 @@ namespace duckmem { }; } //namespace duckmem -#include "ScapegoatMap.inl" +#include "implem/scapegoat_map.inl" #endif diff --git a/include/duckhandy/ScapegoatTree.hpp b/include/duckhandy/scapegoat_tree.hpp similarity index 98% rename from include/duckhandy/ScapegoatTree.hpp rename to include/duckhandy/scapegoat_tree.hpp index 6fb085e..51247b7 100644 --- a/include/duckhandy/ScapegoatTree.hpp +++ b/include/duckhandy/scapegoat_tree.hpp @@ -1,7 +1,7 @@ #ifndef id79CEDB2530B54204A6BEDCBE0B767EA1 #define id79CEDB2530B54204A6BEDCBE0B767EA1 -#include "TreeIterator.hpp" +#include "tree_iterator.hpp" #include "IteratorOnPtr.hpp" #include "SmallObject.hpp" #include "DuckMaths/Functions.hpp" @@ -126,6 +126,6 @@ namespace duckmem { }; } //namespace duckmem -#include "ScapegoatTree.inl" +#include "implem/scapegoat_tree.inl" #endif diff --git a/include/duckhandy/tree_iterator.hpp b/include/duckhandy/tree_iterator.hpp new file mode 100644 index 0000000..c910396 --- /dev/null +++ b/include/duckhandy/tree_iterator.hpp @@ -0,0 +1,121 @@ +#ifndef id6109D5EDE99D43C4909F084A231BF2C2 +#define id6109D5EDE99D43C4909F084A231BF2C2 + +#include "DuckCore/Stack.hpp" +#include "DuckCore/Helpers.hpp" +#include +#include + +namespace duckmem { + namespace Implem { + template + class TreeIterator_base { + template friend class TreeIterator_base; + public: + explicit TreeIterator_base ( void ) {} + TreeIterator_base ( const TreeIterator_base& parOther ); + template + explicit TreeIterator_base ( const TreeIterator_base& parOther ); + ~TreeIterator_base ( void ) {} + protected: + typedef duckcore::Stack > StackType; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + bool Exhausted ( void ) const; + StackType m_stack; + }; + + template + class TreeIterator_const_layer; + template + class TreeIterator_const_layer : protected TreeIterator_base { + template friend class TreeIterator_const_layer; + typedef TreeIterator_base parent_type; + public: + typedef const T* pointer; + typedef const T* const_pointer; + typedef const T& reference; + typedef const T& const_reference; + typedef typename parent_type::size_type size_type; + typedef typename parent_type::difference_type difference_type; + typedef N NodeType; + typedef const N* NodeTypePointer; + enum { IS_CONST = 1 }; + TreeIterator_const_layer ( void ) {} + TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {} + template + explicit TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {} + const_reference operator* ( void ) const; + const_pointer operator-> ( void ) const; + const N* GetPointer ( void ) const; + protected: + typedef typename parent_type::StackType StackType; + }; + template + class TreeIterator_const_layer : protected TreeIterator_base { + template friend class TreeIterator_const_layer; + typedef TreeIterator_base parent_type; + public: + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef typename parent_type::size_type size_type; + typedef typename parent_type::difference_type difference_type; + typedef N NodeType; + typedef N* NodeTypePointer; + enum { IS_CONST = 0 }; + TreeIterator_const_layer ( void ) {} + TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {} + template + explicit TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {} + reference operator* ( void ); + const_reference operator* ( void ) const; + pointer operator-> ( void ); + const_pointer operator-> ( void ) const; + const N* GetPointer ( void ) const; + N* GetPointer ( void ); + protected: + typedef typename parent_type::StackType StackType; + }; + } //namespace Implem + + template + class TreeIterator : public Implem::TreeIterator_const_layer::isConst> { + typedef Implem::TreeIterator_const_layer::isConst> parent_type; + typedef typename parent_type::NodeTypePointer NodeTypePointer; + typedef typename parent_type::NodeType NodeType; + typedef typename parent_type::StackType StackType; + public: + typedef T value_type; + typedef std::forward_iterator_tag iterator_category; + typedef typename parent_type::difference_type difference_type; + typedef typename parent_type::size_type size_type; + typedef typename parent_type::pointer pointer; + typedef typename parent_type::const_pointer const_pointer; + typedef typename parent_type::reference reference; + typedef typename parent_type::const_reference const_reference; + + TreeIterator ( void ); + TreeIterator ( const TreeIterator& parOther ); + TreeIterator ( NodeTypePointer parRoot, size_type parMaxDepthHint ); + template + TreeIterator ( S parCopyStackBottomUp, size_type parStackLen, size_type parMaxDepthHint ); + template + TreeIterator ( const TreeIterator& parOther ); + ~TreeIterator ( void ); + + const TreeIterator& operator= ( const TreeIterator& parOther ); + bool operator== ( const TreeIterator& parOther ) const; + bool operator!= ( const TreeIterator& parOther ) const { return not (*this == parOther); } + TreeIterator& operator++ ( void ); //pre + TreeIterator operator++ ( int ); //post + + private: + void RecurseLeft ( NodeTypePointer parFrom ); + }; +} //namespace duckmem + +#include "implem/tree_iterator.inl" + +#endif From 633532473bb28b00a219a121196b1c20eb272146 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 30 Nov 2018 23:38:25 +0000 Subject: [PATCH 03/60] Fix the build, add unit tests and fix the bugs I spotted so far. --- include/duckhandy/implem/scapegoat_tree.inl | 28 +++---- include/duckhandy/implem/tree_iterator.inl | 40 +++++---- include/duckhandy/log2_fast.hpp | 59 ++++++++++++++ include/duckhandy/scapegoat_tree.hpp | 63 +++++++++------ include/duckhandy/tree_iterator.hpp | 21 +++-- test/unit/CMakeLists.txt | 1 + test/unit/scapegoat_tree_test.cpp | 89 +++++++++++++++++++++ 7 files changed, 240 insertions(+), 61 deletions(-) create mode 100644 include/duckhandy/log2_fast.hpp create mode 100644 test/unit/scapegoat_tree_test.cpp diff --git a/include/duckhandy/implem/scapegoat_tree.inl b/include/duckhandy/implem/scapegoat_tree.inl index 946bfd6..40408d6 100644 --- a/include/duckhandy/implem/scapegoat_tree.inl +++ b/include/duckhandy/implem/scapegoat_tree.inl @@ -45,7 +45,7 @@ namespace duckmem { ///ignore the hint and rely on the normal insert(). ///------------------------------------------------------------------------- template - typename ScapegoatTree::iterator ScapegoatTree::insert (const iterator&, typename Loki::TypeTraits::ParameterType parValue) { + typename ScapegoatTree::iterator ScapegoatTree::insert (const iterator&, const K& parValue) { std::pair retVal = insert(parValue); return retVal.first; } @@ -53,7 +53,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - std::pair::iterator, bool> ScapegoatTree::insert (typename Loki::TypeTraits::ParameterType parKey) { + std::pair::iterator, bool> ScapegoatTree::insert (const K& parKey) { const size_type depthHint = GetMaxBalancedDepth(std::max(m_reserved, m_count + 1), m_alphainvloginv) + 3; #if defined(SCAPEGOATTREE_VERBOSE) std::cout << "insert(): depthHint = " << depthHint << ", m_count = " << m_count << ", m_countMax = " << m_countMax << ", m_reserved = " << m_reserved << std::endl; @@ -101,8 +101,8 @@ namespace duckmem { m_reserved = std::max(m_reserved, m_count); //Update the count of every node - foreach_tn (itNode, stack) { - ++(*itNode)->size; + for (auto& node : stack) { + ++node->size; } //Add the new node to the stack @@ -187,14 +187,14 @@ namespace duckmem { } } AssertNotReached(); - set_not_reached(); + __builtin_unreachable(); return NodeTypePair(NULL, NULL); } ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::GetNewNode (typename Loki::TypeTraits::ParameterType parKey) { + typename ScapegoatTree::NodeType* ScapegoatTree::GetNewNode (const K& parKey) { return new NodeType(parKey); } @@ -202,7 +202,7 @@ namespace duckmem { ///------------------------------------------------------------------------- template template - T* ScapegoatTree::FindClosestMatch (T* parTree, typename Loki::TypeTraits::ParameterType parKey) { + T* ScapegoatTree::FindClosestMatch (T* parTree, const K& parKey) { Assert(NULL != parTree); //if (parTree->left and parKey <= parTree->left->content) if (parTree->left and not (parTree->left->content < parKey)) @@ -217,7 +217,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::GetInsertParent (NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey, NodeStack& parRewind) { + typename ScapegoatTree::NodeType* ScapegoatTree::GetInsertParent (NodeType* parTree, const K& parKey, NodeStack& parRewind) { Assert(NULL != parTree); NodeType* retVal = parTree; bool goLeft; @@ -302,7 +302,7 @@ namespace duckmem { NodeWrapper child(&pseudorootMem); size_type iterationsCount; - if (duckcore::IsPowerOfTwo(vineSize + 1)) + if (implem::IsPowerOfTwo(vineSize + 1)) iterationsCount = (1 << (duckmath::log2_fast(vineSize))) - 1; else iterationsCount = (vineSize - ((1 << duckmath::log2_fast(vineSize)) - 1)); @@ -324,7 +324,7 @@ namespace duckmem { parent.right() = child.pointer(); child.left() = current.pointer(); Assert(z * 2 < vineSize); - child.size() = duckcore::checked_numcast(vineSize - z * 2); + child.size() = static_cast(vineSize - z * 2); Assert(child.size() >= 1); parent.Replace(&child); @@ -336,7 +336,7 @@ namespace duckmem { child.Replace(itFirstStep.GetPointer()); ++itFirstStep; child.left() = NULL; - child.size() = duckcore::checked_numcast(vineSize - z); + child.size() = static_cast(vineSize - z); } child.right() = NULL; child.size() = (child.left() ? 2 : 1); @@ -381,7 +381,7 @@ namespace duckmem { #if defined(SCAPEGOATTREE_VERBOSE) std::cout << "treeSize = " << treeSize << ", vineSize = " << vineSize << ", treeHeight = " << treeHeight << ", manually counted " << countedNodes << " nodes (" << count << ")\n"; #endif - Assert(duckcore::IsPowerOfTwo(countedNodes + 1)); + Assert(implem::IsPowerOfTwo(countedNodes + 1)); Assert(vineSize == countedNodes); } #endif @@ -542,7 +542,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::FindIFP (const NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey) { + typename ScapegoatTree::NodeType* ScapegoatTree::FindIFP (const NodeType* parTree, const K& parKey) { while (parTree) { if (parKey < parTree->content) parTree = parTree->left; @@ -614,7 +614,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - bool ScapegoatTree::Include (typename Loki::TypeTraits::ParameterType parSearch) const { + bool ScapegoatTree::Include (const K& parSearch) const { const NodeType* const found = FindIFP(m_root, parSearch); Assert(not found or not (parSearch < found->content or found->content < parSearch)); return static_cast(NULL != found); diff --git a/include/duckhandy/implem/tree_iterator.inl b/include/duckhandy/implem/tree_iterator.inl index 09a296a..f4d9507 100644 --- a/include/duckhandy/implem/tree_iterator.inl +++ b/include/duckhandy/implem/tree_iterator.inl @@ -11,8 +11,11 @@ namespace duckmem { ///--------------------------------------------------------------------- template TreeIterator_base

::TreeIterator_base (const TreeIterator_base& parOther) : - m_stack(parOther.m_stack) + m_stack() { + m_stack.reserve(parOther.m_stack.capacity()); + m_stack = parOther.m_stack; + Assert(m_stack.capacity() == parOther.m_stack.capacity()); } ///--------------------------------------------------------------------- @@ -31,7 +34,7 @@ namespace duckmem { m_stack.reserve(parOther.m_stack.capacity()); for (typename std::vector

::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) { Assert(m_stack.capacity() > m_stack.size()); - m_stack.push(*itRev); + m_stack.push_back(*itRev); } } @@ -40,7 +43,7 @@ namespace duckmem { template typename TreeIterator_const_layer::reference TreeIterator_const_layer::operator* () { AssertRelease(not this->Exhausted()); - return this->m_stack.top()->content; + return this->m_stack.back()->content; } ///--------------------------------------------------------------------- @@ -48,7 +51,7 @@ namespace duckmem { template typename TreeIterator_const_layer::const_reference TreeIterator_const_layer::operator* () const { AssertRelease(not this->Exhausted()); - return this->m_stack.top()->content; + return this->m_stack.back()->content; } ///--------------------------------------------------------------------- @@ -56,7 +59,7 @@ namespace duckmem { template typename TreeIterator_const_layer::pointer TreeIterator_const_layer::operator-> () { AssertRelease(not this->Exhausted()); - return &this->m_stack.top()->content; + return &this->m_stack.back()->content; } ///--------------------------------------------------------------------- @@ -64,7 +67,7 @@ namespace duckmem { template typename TreeIterator_const_layer::const_pointer TreeIterator_const_layer::operator-> () const { AssertRelease(not this->Exhausted()); - return &this->m_stack.top()->content; + return &this->m_stack.back()->content; } ///--------------------------------------------------------------------- @@ -72,7 +75,7 @@ namespace duckmem { template N* TreeIterator_const_layer::GetPointer() { AssertRelease(not this->Exhausted()); - return this->m_stack.top(); + return this->m_stack.back(); } ///--------------------------------------------------------------------- @@ -80,7 +83,7 @@ namespace duckmem { template const N* TreeIterator_const_layer::GetPointer() const { AssertRelease(not this->Exhausted()); - return this->m_stack.top(); + return this->m_stack.back(); } ///--------------------------------------------------------------------- @@ -88,7 +91,7 @@ namespace duckmem { template typename TreeIterator_const_layer::const_reference TreeIterator_const_layer::operator* () const { AssertRelease(not this->Exhausted()); - return this->m_stack.top()->content; + return this->m_stack.back()->content; } ///--------------------------------------------------------------------- @@ -96,7 +99,7 @@ namespace duckmem { template typename TreeIterator_const_layer::const_pointer TreeIterator_const_layer::operator-> () const { AssertRelease(not this->Exhausted()); - return &this->m_stack.top()->content; + return &this->m_stack.back()->content; } ///--------------------------------------------------------------------- @@ -104,7 +107,7 @@ namespace duckmem { template const N* TreeIterator_const_layer::GetPointer() const { AssertRelease(not this->Exhausted()); - return this->m_stack.top(); + return this->m_stack.back(); } } //namespace Implem @@ -140,18 +143,20 @@ namespace duckmem { this->m_stack.reserve(std::max(parStackLen, parMaxDepthHint)); typename StackType::value_type prevNode = *parCopyStackBottomUp; ++parCopyStackBottomUp; - this->m_stack.push(prevNode); + this->m_stack.push_back(prevNode); for (size_type z = 1; z < parStackLen; ++z) { typename StackType::value_type currNode = *parCopyStackBottomUp; if (prevNode->left == currNode) { Assert(this->m_stack.capacity() > this->m_stack.size()); - this->m_stack.push(currNode); + this->m_stack.push_back(currNode); } else { //If you get this assertion make sure the iterator you are //passing in is reversed (ie: from leaf to root) AssertRelease(currNode == prevNode->right); + this->m_stack.pop_back(); + this->m_stack.push_back(currNode); } prevNode = currNode; @@ -192,11 +197,12 @@ namespace duckmem { template TreeIterator& TreeIterator::operator++() { AssertRelease(not this->Exhausted()); - NodeTypePointer currNode = this->m_stack.top(); + NodeTypePointer currNode = this->m_stack.back(); #if defined(ASSERTIONSENABLED) const size_type stackCapacity = this->m_stack.capacity(); #endif - this->m_stack.pop(); + AssertRelease(not this->m_stack.empty()); + this->m_stack.pop_back(); #if defined(ASSERTIONSENABLED) //It shouldn't normally happen, but it's just to make sure Assert(stackCapacity == this->m_stack.capacity()); @@ -218,7 +224,7 @@ namespace duckmem { ///------------------------------------------------------------------------- template bool TreeIterator::operator== (const TreeIterator& parOther) const { - return this->m_stack.size() == parOther.m_stack.size() and (this->m_stack.empty() or parOther.m_stack.top() == this->m_stack.top()); + return this->m_stack.size() == parOther.m_stack.size() and (this->m_stack.empty() or parOther.m_stack.back() == this->m_stack.back()); } ///------------------------------------------------------------------------- @@ -228,7 +234,7 @@ namespace duckmem { NodeTypePointer currNode = parFrom; while (NULL != currNode) { Assert(this->m_stack.capacity() > this->m_stack.size()); - this->m_stack.push(currNode); + this->m_stack.push_back(currNode); currNode = currNode->left; } } diff --git a/include/duckhandy/log2_fast.hpp b/include/duckhandy/log2_fast.hpp new file mode 100644 index 0000000..65e5d6a --- /dev/null +++ b/include/duckhandy/log2_fast.hpp @@ -0,0 +1,59 @@ +#ifndef id28695193476D4A9499151FC175A49196 +#define id28695193476D4A9499151FC175A49196 + +#include +#if defined(__linux) +# include +#endif + +namespace duckmath { + namespace implem { +#if !defined(__linux) + [[gnu::pure]] + inline uint_fast32_t LowestBitSet ( uint_fast32_t x ) pure_function; + + //Precomputed lookup table + const constexpr uint_fast32_t g_multiplyDeBruijnBitPosition[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + + ///--------------------------------------------------------------------- + ///Thanks to: http://bits.stephan-brumme.com/lowestBitSet.html + ///--------------------------------------------------------------------- + [[gnu::pure]] + inline uint_fast32_t LowestBitSet (uint_fast32_t x) { + //Leave only lowest bit + x &= -i32(x); + //DeBruijn constant + x *= 0x077CB531; + //Get upper 5 bits + x >>= 27; + //Convert to actual position + return g_multiplyDeBruijnBitPosition[x]; + } +#endif + + [[gnu::pure]] + inline uint32_t GetHighestBitOnly (uint32_t parIn) { + parIn |= (parIn >> 1); + parIn |= (parIn >> 2); + parIn |= (parIn >> 4); + parIn |= (parIn >> 8); + parIn |= (parIn >> 16); + return parIn - (parIn >> 1); + } + } //namespace implem + + uint_fast32_t log2_fast (uint_fast32_t parX) { + const uint_fast32_t highestPow2 = implem::GetHighestBitOnly(parX); +#if defined(__linux) + const uint_fast32_t retVal = ffs(highestPow2) - 1; +#else + const uint_fast32_t retVal = LowestBitSet(highestPow2); +#endif + return retVal; + } +} //namespace duckmath + +#endif diff --git a/include/duckhandy/scapegoat_tree.hpp b/include/duckhandy/scapegoat_tree.hpp index 51247b7..e7b3413 100644 --- a/include/duckhandy/scapegoat_tree.hpp +++ b/include/duckhandy/scapegoat_tree.hpp @@ -2,15 +2,13 @@ #define id79CEDB2530B54204A6BEDCBE0B767EA1 #include "tree_iterator.hpp" -#include "IteratorOnPtr.hpp" -#include "SmallObject.hpp" -#include "DuckMaths/Functions.hpp" -#include "DuckCore/Helpers.hpp" -#include "DuckCore/foreach.hpp" -#include "DuckCore/Casts.hpp" +#include "implem/IteratorOnPtr.hpp" +#include "log2_fast.hpp" #include #include #include +#include +#include //#define SCAPEGOATTREE_VERBOSE //#define SCAPEGOATTREE_PARANOID @@ -29,9 +27,24 @@ #endif namespace duckmem { -#if defined(WITH_DEBUG_TESTS) - bool RunScapegoatTests ( void ); -#endif + using dhandy::IteratorOnPtr; + + namespace implem { + [[gnu::pure]] + inline bool IsPowerOfTwo (unsigned int parValue) { + return (parValue != 0 and (parValue bitand (~parValue + 1)) == parValue); + } + } //namespace implem + + //TODO: implement or remove + class SmallObject { + public: + protected: + SmallObject ( void )=default; + ~SmallObject ( void ) noexcept =default; + + private: + }; template class ScapegoatTree { @@ -44,7 +57,7 @@ namespace duckmem { struct TreeNodeStruct : public SmallObject { typedef SizeType size_type; TreeNodeStruct ( void ); - TreeNodeStruct ( typename Loki::TypeTraits::ParameterType parContent ) : content(parContent) {} + TreeNodeStruct ( const K& parContent ) : content(parContent) {} K content; TreeNodeStruct* left; @@ -52,13 +65,13 @@ namespace duckmem { size_type size; }; #if defined(SCAPEGOATTREE_DYNAMIC_SIZE_TYPE) - typedef typename duckcore::Iif) == sizeof(TreeNodeStruct), size_type, u32>::Result TreeNodeSizeType; + typedef typename std::conditional) == sizeof(TreeNodeStruct), size_type, uint32_t>::type TreeNodeSizeType; typedef TreeNodeStruct TreeNode; #else typedef TreeNodeStruct TreeNode; #endif - STATIC_ASSERT(sizeof(typename TreeNode::size_type) <= sizeof(size_type)); + static_assert(sizeof(typename TreeNode::size_type) <= sizeof(size_type), "Mismatching size_type size"); typedef TreeNode NodeType; typedef std::vector NodeStack; typedef std::pair NodeTypePair; @@ -68,17 +81,17 @@ namespace duckmem { typedef value_type& reference; typedef const value_type* const_pointer; typedef const value_type& const_reference; - typedef TreeIterator iterator; - typedef TreeIterator const_iterator; + typedef duckmem::TreeIterator iterator; + typedef duckmem::TreeIterator const_iterator; ScapegoatTree ( void ); explicit ScapegoatTree ( float parAlpha ); ~ScapegoatTree ( void ); float GetAlpha ( void ) const { return m_alpha; } - bool Include ( typename Loki::TypeTraits::ParameterType parSearch ) const; - std::pair insert ( typename Loki::TypeTraits::ParameterType parKey ); - iterator insert ( const iterator&, typename Loki::TypeTraits::ParameterType parValue ); + bool Include ( const K& parSearch ) const; + std::pair insert ( const K& parKey ); + iterator insert ( const iterator&, const K& parValue ); bool empty ( void ) const { return m_count == 0; } size_type size ( void ) const { return m_count; } void reserve ( size_type parSize ) { m_reserved = std::max(parSize, m_count); } @@ -86,7 +99,7 @@ namespace duckmem { void clear ( void ); void erase ( iterator parItem ); void erase ( iterator parFrom, iterator parLast ); - size_type erase ( typename Loki::TypeTraits::ParameterType parKey ); + size_type erase ( const value_type& parKey ); iterator begin ( void ); const_iterator begin ( void ) const; @@ -95,19 +108,19 @@ namespace duckmem { private: template - static T* FindClosestMatch ( T* parTree, typename Loki::TypeTraits::ParameterType parKey ); - static NodeType* GetInsertParent ( NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey, NodeStack& parRewind ); - static NodeType* FindIFP ( const NodeType* parTree, typename Loki::TypeTraits::ParameterType parKey ); + static T* FindClosestMatch ( T* parTree, const K& parKey ); + static NodeType* GetInsertParent ( NodeType* parTree, const K& parKey, NodeStack& parRewind ); + static NodeType* FindIFP ( const NodeType* parTree, const K& parKey ); static NodeType* FindParentIFP ( NodeType* parTree, const NodeType* parSearchNodeAddr ); - static NodeType* GetNewNode ( typename Loki::TypeTraits::ParameterType parKey ); + static NodeType* GetNewNode ( const K& parKey ); static void DeleteNodes ( NodeType* parNode ); - bool IsAlphaHeightBalanced ( size_type parHeight, size_type parSize ) const pure_function; + [[gnu::pure]] bool IsAlphaHeightBalanced ( size_type parHeight, size_type parSize ) const; NodeTypePair FindScapegoat ( NodeStack& parParents ) const; static NodeType* Rebalance ( NodeType* parSubtree, size_type parDepthHint ); static NodeType* Compress_first ( NodeType* parFrom, size_type parDepthHint ); static NodeType* Compress ( NodeType* parFrom ); - static size_type GetMaxBalancedDepth ( size_type parSize, float parAlphaInvLogInv ) pure_function; - static size_type GetTreeMinDepthIB ( size_type parSize, float parAlphaInvLogInv ) pure_function; + [[gnu::pure]] static size_type GetMaxBalancedDepth ( size_type parSize, float parAlphaInvLogInv ); + [[gnu::pure]] static size_type GetTreeMinDepthIB ( size_type parSize, float parAlphaInvLogInv ); static NodeType* DetachBottomNode ( NodeType* parTree, bool parSuccessor ); void RebalanceAfterDeletionIFN ( void ); diff --git a/include/duckhandy/tree_iterator.hpp b/include/duckhandy/tree_iterator.hpp index c910396..258d3a9 100644 --- a/include/duckhandy/tree_iterator.hpp +++ b/include/duckhandy/tree_iterator.hpp @@ -1,10 +1,20 @@ #ifndef id6109D5EDE99D43C4909F084A231BF2C2 #define id6109D5EDE99D43C4909F084A231BF2C2 -#include "DuckCore/Stack.hpp" -#include "DuckCore/Helpers.hpp" #include #include +#include +#include + +#if !defined(AssertNotReached) +# define AssertNotReached() assert(false) +#endif +#if !defined(AssertRelease) +# define AssertRelease(a) assert(a) +#endif +#if !defined(Assert) +# define Assert(a) assert(a) +#endif namespace duckmem { namespace Implem { @@ -18,7 +28,7 @@ namespace duckmem { explicit TreeIterator_base ( const TreeIterator_base& parOther ); ~TreeIterator_base ( void ) {} protected: - typedef duckcore::Stack > StackType; + typedef std::vector

StackType; typedef size_t size_type; typedef ptrdiff_t difference_type; bool Exhausted ( void ) const; @@ -43,6 +53,7 @@ namespace duckmem { enum { IS_CONST = 1 }; TreeIterator_const_layer ( void ) {} TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {} + TreeIterator_const_layer ( TreeIterator_const_layer&& ) = default; template explicit TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {} const_reference operator* ( void ) const; @@ -81,8 +92,8 @@ namespace duckmem { } //namespace Implem template - class TreeIterator : public Implem::TreeIterator_const_layer::isConst> { - typedef Implem::TreeIterator_const_layer::isConst> parent_type; + class TreeIterator : public Implem::TreeIterator_const_layer::value> { + typedef Implem::TreeIterator_const_layer::value> parent_type; typedef typename parent_type::NodeTypePointer NodeTypePointer; typedef typename parent_type::NodeType NodeType; typedef typename parent_type::StackType StackType; diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index c13f53e..c259d42 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -8,6 +8,7 @@ add_executable(${PROJECT_NAME} reversed_sized_array_test.cpp bitfield_pack_test.cpp resource_pool_test.cpp + scapegoat_tree_test.cpp ) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/test/unit/scapegoat_tree_test.cpp b/test/unit/scapegoat_tree_test.cpp new file mode 100644 index 0000000..cf531b8 --- /dev/null +++ b/test/unit/scapegoat_tree_test.cpp @@ -0,0 +1,89 @@ +/* Copyright 2016-2018 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#include "catch2/catch.hpp" +#include "duckhandy/scapegoat_tree.hpp" + +TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") { + using duckmem::ScapegoatTree; + + ScapegoatTree tree; + { + auto it = tree.insert(25); + CHECK(it.second == true); + CHECK(it.first != tree.end()); + CHECK(*it.first == 25); + CHECK(tree.size() == 1); + } + + { + auto it = tree.insert(25); + CHECK(tree.size() == 1); + CHECK(it.second == false); + CHECK(it.first != tree.end()); + CHECK(*it.first == 25); + } + + { + auto it = tree.insert(26); + CHECK(it.second == true); + CHECK(it.first != tree.end()); + CHECK(*it.first == 26); + CHECK(tree.size() == 2); + } + + { + for (std::size_t z = 0; z < 100; ++z) { + const int val = static_cast(z); + + auto it = tree.insert(val); + if (z < 25) { + CHECK(tree.size() == z + 2 + 1); + CHECK(it.second == true); + } + else if (z < 26) { + CHECK(tree.size() == z + 1 + 1); + CHECK(it.second == false); + } + else if (z < 27) { + CHECK(tree.size() == z + 1); + CHECK(it.second == false); + } + else { + CHECK(tree.size() == z + 1); + CHECK(it.second == true); + } + CHECK(*it.first == val); + } + } + + { + auto end = tree.end(); + int val = 0; + for (auto it = tree.begin(); it != end; ++it, ++val) { + CHECK(val == *it); + } + CHECK(static_cast(tree.size()) == val); + + val = 75; + for (auto it = tree.insert(val).first; it != end; ++it, ++val) { + CHECK(val == *it); + } + CHECK(static_cast(tree.size()) == val); + } +} + From 08b3591c60d3a243147b5cf16855235407c0dae8 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 13 Aug 2020 21:03:50 +0100 Subject: [PATCH 04/60] Adjust naming convention --- include/duckhandy/implem/scapegoat_tree.inl | 106 ++++++++++---------- include/duckhandy/scapegoat_tree.hpp | 42 ++++---- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/include/duckhandy/implem/scapegoat_tree.inl b/include/duckhandy/implem/scapegoat_tree.inl index 40408d6..6095fc7 100644 --- a/include/duckhandy/implem/scapegoat_tree.inl +++ b/include/duckhandy/implem/scapegoat_tree.inl @@ -31,7 +31,7 @@ namespace duckmem { ///------------------------------------------------------------------------- template ScapegoatTree::~ScapegoatTree() { - DeleteNodes(m_root); + delete_nodes(m_root); #if defined(DUCK_DEBUG) m_root = NULL; m_count = 0xDEADBEEF; @@ -54,12 +54,12 @@ namespace duckmem { ///------------------------------------------------------------------------- template std::pair::iterator, bool> ScapegoatTree::insert (const K& parKey) { - const size_type depthHint = GetMaxBalancedDepth(std::max(m_reserved, m_count + 1), m_alphainvloginv) + 3; + const size_type depthHint = get_max_balanced_depth(std::max(m_reserved, m_count + 1), m_alphainvloginv) + 3; #if defined(SCAPEGOATTREE_VERBOSE) std::cout << "insert(): depthHint = " << depthHint << ", m_count = " << m_count << ", m_countMax = " << m_countMax << ", m_reserved = " << m_reserved << std::endl; #endif if (NULL == m_root) { - m_root = GetNewNode(parKey); + m_root = get_new_node(parKey); m_root->left = m_root->right = NULL; m_root->size = 1; m_count = 1; @@ -79,13 +79,13 @@ namespace duckmem { NodeStack stack; stack.reserve(depthHint); - NodeType* const closestMatch = GetInsertParent(m_root, parKey, stack); + NodeType* const closestMatch = get_insert_parent(m_root, parKey, stack); Assert(stack.size() <= depthHint); if (closestMatch->content == parKey) return std::pair(iterator(stack.begin(), stack.size(), depthHint), false); Assert(NULL == closestMatch->left or closestMatch->left->content < parKey); Assert(NULL == closestMatch->right or parKey < closestMatch->right->content); - NodeType* const newNode = GetNewNode(parKey); + NodeType* const newNode = get_new_node(parKey); newNode->left = newNode->right = NULL; newNode->size = 1; if (parKey < closestMatch->content) { @@ -116,14 +116,14 @@ namespace duckmem { size_type newNodeDepth = stack.size() - 1; //Rebalance if necessary - if (not IsAlphaHeightBalanced(newNodeDepth, this->size())) { + if (not is_alpha_height_balanced(newNodeDepth, this->size())) { #if defined(SCAPEGOATTREE_PARANOID) - Assert(FindMaxDepth(m_root) == newNodeDepth); + Assert(find_max_depth(m_root) == newNodeDepth); #endif - Assert(GetMaxBalancedDepth(static_cast(m_root->size), m_alphainvloginv) + 1 == newNodeDepth); - std::pair scapegoatAndParent = FindScapegoat(stack); + Assert(get_max_balanced_depth(static_cast(m_root->size), m_alphainvloginv) + 1 == newNodeDepth); + std::pair scapegoatAndParent = find_scapegoat(stack); AssertRelease(NULL != scapegoatAndParent.first); - NodeType* const newRoot = Rebalance(scapegoatAndParent.first, newNodeDepth + 1); + NodeType* const newRoot = rebalance(scapegoatAndParent.first, newNodeDepth + 1); NodeType* const parent = scapegoatAndParent.second; if (parent == NULL) { Assert(scapegoatAndParent.first == m_root); @@ -142,14 +142,14 @@ namespace duckmem { } #if defined(SCAPEGOATTREE_PARANOID) AssertNodeSize(m_root); - Assert(FindMaxDepth(m_root) <= GetMaxBalancedDepth(static_cast(m_root->size), m_alphainvloginv)); + Assert(find_max_depth(m_root) <= get_max_balanced_depth(static_cast(m_root->size), m_alphainvloginv)); #endif //Rebuild the stack. //TODO: this is ugly and slow, see if you can find a better way stack.clear(); - GetInsertParent(m_root, parKey, stack); + get_insert_parent(m_root, parKey, stack); newNodeDepth = stack.size() - 1; - Assert(IsAlphaHeightBalanced(newNodeDepth, this->size())); + Assert(is_alpha_height_balanced(newNodeDepth, this->size())); } return std::pair(iterator(stack.begin(), newNodeDepth + 1, duckmath::log2_fast(m_reserved + 1)), true); } @@ -158,26 +158,26 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::Rebalance (NodeType* parSubtree, size_type parDepthHint) { + typename ScapegoatTree::NodeType* ScapegoatTree::rebalance (NodeType* parSubtree, size_type parDepthHint) { #if defined(SCAPEGOATTREE_VERBOSE) std::cout << "Rebalancing subtree" << std::endl; #endif Assert(NULL != parSubtree); - NodeType* const newRoot = Compress_first(parSubtree, parDepthHint); - NodeType* const retVal = Compress(newRoot); + NodeType* const newRoot = compress_first(parSubtree, parDepthHint); + NodeType* const retVal = compress(newRoot); return retVal; } ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeTypePair ScapegoatTree::FindScapegoat (NodeStack& parParents) const { + typename ScapegoatTree::NodeTypePair ScapegoatTree::find_scapegoat (NodeStack& parParents) const { Assert(not parParents.empty()); const size_type height = parParents.size(); for (size_type z = parParents.size() - 1; z > 0; --z) { NodeType& currNode = *(parParents[z - 1]); Assert(height - z > 0); - if (not IsAlphaHeightBalanced(height - z, static_cast(currNode.size))) { + if (not is_alpha_height_balanced(height - z, static_cast(currNode.size))) { NodeType* parent; if (z == 1) parent = NULL; @@ -194,7 +194,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::GetNewNode (const K& parKey) { + typename ScapegoatTree::NodeType* ScapegoatTree::get_new_node (const K& parKey) { return new NodeType(parKey); } @@ -202,7 +202,7 @@ namespace duckmem { ///------------------------------------------------------------------------- template template - T* ScapegoatTree::FindClosestMatch (T* parTree, const K& parKey) { + T* ScapegoatTree::find_closest_match (T* parTree, const K& parKey) { Assert(NULL != parTree); //if (parTree->left and parKey <= parTree->left->content) if (parTree->left and not (parTree->left->content < parKey)) @@ -217,7 +217,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::GetInsertParent (NodeType* parTree, const K& parKey, NodeStack& parRewind) { + typename ScapegoatTree::NodeType* ScapegoatTree::get_insert_parent (NodeType* parTree, const K& parKey, NodeStack& parRewind) { Assert(NULL != parTree); NodeType* retVal = parTree; bool goLeft; @@ -243,10 +243,10 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - void ScapegoatTree::DeleteNodes (NodeType* parNode) { + void ScapegoatTree::delete_nodes (NodeType* parNode) { if (parNode) { - DeleteNodes(parNode->left); - DeleteNodes(parNode->right); + delete_nodes(parNode->left); + delete_nodes(parNode->right); delete parNode; } } @@ -254,7 +254,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - bool ScapegoatTree::IsAlphaHeightBalanced (size_type parHeight, size_type parSize) const { + bool ScapegoatTree::is_alpha_height_balanced (size_type parHeight, size_type parSize) const { const float sz = static_cast(parSize); const float ha = std::floor(std::log(sz) * m_alphainvloginv); const float height = static_cast(parHeight); @@ -264,15 +264,15 @@ namespace duckmem { ///------------------------------------------------------------------------- ///Stout/Warren vine to tree. ///This function destroys the links of the given subtree and creates a - ///structure that is suitable for Compress(). Input is treated as if it + ///structure that is suitable for compress(). Input is treated as if it ///was a linked list. ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::Compress_first (NodeType* parFrom, size_type parDepthHint) { + typename ScapegoatTree::NodeType* ScapegoatTree::compress_first (NodeType* parFrom, size_type parDepthHint) { const size_type vineSize = static_cast(parFrom->size); const size_type iteratorDepth = parDepthHint; #if defined(SCAPEGOATTREE_VERBOSE) - std::cout << "Compress_first(): vineSize = " << vineSize << ", iteratorDepth = " << iteratorDepth << std::endl; + std::cout << "compress_first(): vineSize = " << vineSize << ", iteratorDepth = " << iteratorDepth << std::endl; #endif iterator itFirstStep(parFrom, iteratorDepth); @@ -302,7 +302,7 @@ namespace duckmem { NodeWrapper child(&pseudorootMem); size_type iterationsCount; - if (implem::IsPowerOfTwo(vineSize + 1)) + if (implem::is_power_of_two(vineSize + 1)) iterationsCount = (1 << (duckmath::log2_fast(vineSize))) - 1; else iterationsCount = (vineSize - ((1 << duckmath::log2_fast(vineSize)) - 1)); @@ -347,7 +347,7 @@ namespace duckmem { Assert(vineSize == static_cast(pseudorootMem.right->size)); #if defined(SCAPEGOATTREE_PARANOID) AssertNodeSize(pseudorootMem.right); - Assert(FindMaxDepth(pseudorootMem.right) <= vineSize); + Assert(find_max_depth(pseudorootMem.right) <= vineSize); #endif return pseudorootMem.right; } @@ -357,7 +357,7 @@ namespace duckmem { ///Performs the second and subsequent steps for compressing. ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::Compress (NodeType* parFrom) { + typename ScapegoatTree::NodeType* ScapegoatTree::compress (NodeType* parFrom) { Assert(NULL != parFrom); //We don't know if the tree is complete, so let's calculate its depth //rounded up to the nearest complete tree @@ -366,7 +366,7 @@ namespace duckmem { const size_type treeHeight = duckmath::log2_fast(treeSize + (1 << m)); #if defined(SCAPEGOATTREE_PARANOID) - size_type maxDepthInTree = FindMaxDepth(parFrom); + size_type maxDepthInTree = find_max_depth(parFrom); { //We know step 0 of compression has already been done, so on with //the spine size at step 1 (the one we're willing to do) @@ -381,7 +381,7 @@ namespace duckmem { #if defined(SCAPEGOATTREE_VERBOSE) std::cout << "treeSize = " << treeSize << ", vineSize = " << vineSize << ", treeHeight = " << treeHeight << ", manually counted " << countedNodes << " nodes (" << count << ")\n"; #endif - Assert(implem::IsPowerOfTwo(countedNodes + 1)); + Assert(implem::is_power_of_two(countedNodes + 1)); Assert(vineSize == countedNodes); } #endif @@ -392,7 +392,7 @@ namespace duckmem { for (size_type k = 1; k < treeHeight - 1; ++k) { #if defined(SCAPEGOATTREE_VERBOSE) - std::cout << "Compress() step " << k << std::endl; + std::cout << "compress() step " << k << std::endl; #endif //The rebalanced tree takes treeHeight-1 steps. One step has been done //already, so we perform the remaining treeHeight-2 steps. @@ -431,7 +431,7 @@ namespace duckmem { #if defined(SCAPEGOATTREE_PARANOID) AssertNodeSize(retVal); { - const size_type newDepth = FindMaxDepth(retVal); + const size_type newDepth = find_max_depth(retVal); Assert(newDepth <= maxDepthInTree); maxDepthInTree = newDepth; } @@ -446,7 +446,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::size_type ScapegoatTree::AssertNodeSize (const NodeType* parSubtree) { + typename ScapegoatTree::size_type ScapegoatTree::assert_node_size (const NodeType* parSubtree) { Assert(parSubtree); typename NodeType::size_type localSize = 1; @@ -463,7 +463,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::size_type ScapegoatTree::FindMaxDepth_rec (const NodeType* parSubtree) { + typename ScapegoatTree::size_type ScapegoatTree::find_max_depth_rec (const NodeType* parSubtree) { Assert(parSubtree); typename NodeType::size_type depthLeft = 0; typename NodeType::size_type depthRight = 0; @@ -482,7 +482,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::size_type ScapegoatTree::GetMaxBalancedDepth (size_type parSize, float parAlphaInvLogInv) { + typename ScapegoatTree::size_type ScapegoatTree::get_max_balanced_depth (size_type parSize, float parAlphaInvLogInv) { const float ha = std::log(static_cast(parSize)) * parAlphaInvLogInv; return static_cast(ha); } @@ -494,10 +494,10 @@ namespace duckmem { if (NULL == m_root) return iterator(); - const size_type depthHint = GetTreeMinDepthIB(m_reserved, m_alphainvloginv) + 1; + const size_type depthHint = get_tree_min_depth_ib(m_reserved, m_alphainvloginv) + 1; #if defined(SCAPEGOATTREE_PARANOID) - Assert(IsAlphaHeightBalanced(FindMaxDepth(m_root), static_cast(m_root->size))); - Assert(FindMaxDepth(m_root) + 1 <= depthHint); + Assert(is_alpha_height_balanced(find_max_depth(m_root), static_cast(m_root->size))); + Assert(find_max_depth(m_root) + 1 <= depthHint); #endif return iterator(m_root, depthHint + 1); } @@ -509,10 +509,10 @@ namespace duckmem { if (NULL == m_root) return iterator(); - const size_type depthHint = GetTreeMinDepthIB(m_count, m_alphainvloginv) + 1; + const size_type depthHint = get_tree_min_depth_ib(m_count, m_alphainvloginv) + 1; #if defined(SCAPEGOATTREE_PARANOID) - Assert(IsAlphaHeightBalanced(FindMaxDepth(m_root), static_cast(m_root->size))); - Assert(FindMaxDepth(m_root) + 1 <= depthHint); + Assert(is_alpha_height_balanced(find_max_depth(m_root), static_cast(m_root->size))); + Assert(find_max_depth(m_root) + 1 <= depthHint); #endif return const_iterator(m_root, depthHint + 1); } @@ -521,7 +521,7 @@ namespace duckmem { ///Get min tree depth if balanced ///------------------------------------------------------------------------- template - typename ScapegoatTree::size_type ScapegoatTree::GetTreeMinDepthIB (size_type parSize, float parAlphaInvLogInv) { + typename ScapegoatTree::size_type ScapegoatTree::get_tree_min_depth_ib (size_type parSize, float parAlphaInvLogInv) { const float sz = static_cast(parSize); const size_type roundedDownDepthBase2 = duckmath::log2_fast(parSize + 1); const float nodesAtLastLevel = (roundedDownDepthBase2 == 0 ? 0 : static_cast(1 << roundedDownDepthBase2) - 1.0f); @@ -533,7 +533,7 @@ namespace duckmem { ///------------------------------------------------------------------------- template void ScapegoatTree::clear() { - DeleteNodes(m_root); + delete_nodes(m_root); m_count = 0; m_countMax = 0; m_root = NULL; @@ -542,7 +542,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::FindIFP (const NodeType* parTree, const K& parKey) { + typename ScapegoatTree::NodeType* ScapegoatTree::find_ifp (const NodeType* parTree, const K& parKey) { while (parTree) { if (parKey < parTree->content) parTree = parTree->left; @@ -557,7 +557,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::FindParentIFP (NodeType* parTree, const NodeType* parSearchNodeAddr) { + typename ScapegoatTree::NodeType* ScapegoatTree::find_parent_ifp (NodeType* parTree, const NodeType* parSearchNodeAddr) { if (parTree == parSearchNodeAddr) return NULL; NodeType* parent = parTree; @@ -578,7 +578,7 @@ namespace duckmem { ///get the in-order predecessor. ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::DetachBottomNode (NodeType* parTree, bool parSuccessor) { + typename ScapegoatTree::NodeType* ScapegoatTree::detach_bottom_node (NodeType* parTree, bool parSuccessor) { AssertRelease(NULL != parTree); AssertRelease(NULL != parTree->left and NULL != parTree->right); if (parSuccessor) { @@ -614,7 +614,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - bool ScapegoatTree::Include (const K& parSearch) const { + bool ScapegoatTree::include (const K& parSearch) const { const NodeType* const found = FindIFP(m_root, parSearch); Assert(not found or not (parSearch < found->content or found->content < parSearch)); return static_cast(NULL != found); @@ -623,12 +623,12 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - void ScapegoatTree::RebalanceAfterDeletionIFN() { + void ScapegoatTree::rebalance_after_deletion_ifn() { const float sz = static_cast(m_count); const float m = static_cast(m_countMax); if (sz < m_alpha * m) { const size_type sizeHint = static_cast(std::ceil(std::log(sz) * m_alphainvloginv)) + 1; - Rebalance(m_root, sizeHint); + rebalance(m_root, sizeHint); m_countMax = m_count; } } @@ -669,7 +669,7 @@ namespace duckmem { } --m_count; delete dele; - RebalanceAfterDeletionIFN(); + rebalance_after_deletion_ifn(); } // ///------------------------------------------------------------------------- diff --git a/include/duckhandy/scapegoat_tree.hpp b/include/duckhandy/scapegoat_tree.hpp index e7b3413..362e07a 100644 --- a/include/duckhandy/scapegoat_tree.hpp +++ b/include/duckhandy/scapegoat_tree.hpp @@ -31,7 +31,7 @@ namespace duckmem { namespace implem { [[gnu::pure]] - inline bool IsPowerOfTwo (unsigned int parValue) { + inline bool is_power_of_two (unsigned int parValue) { return (parValue != 0 and (parValue bitand (~parValue + 1)) == parValue); } } //namespace implem @@ -88,8 +88,8 @@ namespace duckmem { explicit ScapegoatTree ( float parAlpha ); ~ScapegoatTree ( void ); - float GetAlpha ( void ) const { return m_alpha; } - bool Include ( const K& parSearch ) const; + float get_alpha ( void ) const { return m_alpha; } + bool include ( const K& parSearch ) const; std::pair insert ( const K& parKey ); iterator insert ( const iterator&, const K& parValue ); bool empty ( void ) const { return m_count == 0; } @@ -108,26 +108,26 @@ namespace duckmem { private: template - static T* FindClosestMatch ( T* parTree, const K& parKey ); - static NodeType* GetInsertParent ( NodeType* parTree, const K& parKey, NodeStack& parRewind ); - static NodeType* FindIFP ( const NodeType* parTree, const K& parKey ); - static NodeType* FindParentIFP ( NodeType* parTree, const NodeType* parSearchNodeAddr ); - static NodeType* GetNewNode ( const K& parKey ); - static void DeleteNodes ( NodeType* parNode ); - [[gnu::pure]] bool IsAlphaHeightBalanced ( size_type parHeight, size_type parSize ) const; - NodeTypePair FindScapegoat ( NodeStack& parParents ) const; - static NodeType* Rebalance ( NodeType* parSubtree, size_type parDepthHint ); - static NodeType* Compress_first ( NodeType* parFrom, size_type parDepthHint ); - static NodeType* Compress ( NodeType* parFrom ); - [[gnu::pure]] static size_type GetMaxBalancedDepth ( size_type parSize, float parAlphaInvLogInv ); - [[gnu::pure]] static size_type GetTreeMinDepthIB ( size_type parSize, float parAlphaInvLogInv ); - static NodeType* DetachBottomNode ( NodeType* parTree, bool parSuccessor ); - void RebalanceAfterDeletionIFN ( void ); + static T* find_closest_match ( T* parTree, const K& parKey ); + static NodeType* get_insert_parent ( NodeType* parTree, const K& parKey, NodeStack& parRewind ); + static NodeType* find_ifp ( const NodeType* parTree, const K& parKey ); + static NodeType* find_parent_ifp ( NodeType* parTree, const NodeType* parSearchNodeAddr ); + static NodeType* get_new_node ( const K& parKey ); + static void delete_nodes ( NodeType* parNode ); + [[gnu::pure]] bool is_alpha_height_balanced ( size_type parHeight, size_type parSize ) const; + NodeTypePair find_scapegoat ( NodeStack& parParents ) const; + static NodeType* rebalance ( NodeType* parSubtree, size_type parDepthHint ); + static NodeType* compress_first ( NodeType* parFrom, size_type parDepthHint ); + static NodeType* compress ( NodeType* parFrom ); + [[gnu::pure]] static size_type get_max_balanced_depth ( size_type parSize, float parAlphaInvLogInv ); + [[gnu::pure]] static size_type get_tree_min_depth_ib ( size_type parSize, float parAlphaInvLogInv ); + static NodeType* detach_bottom_node ( NodeType* parTree, bool parSuccessor ); + void rebalance_after_deletion_ifn ( void ); #if defined(SCAPEGOATTREE_PARANOID) - static size_type AssertNodeSize ( const NodeType* parSubtree ); - static size_type FindMaxDepth ( const NodeType* parSubtree ) { return FindMaxDepth_rec(parSubtree) - 1; } - static size_type FindMaxDepth_rec ( const NodeType* parSubtree ); + static size_type assert_node_size ( const NodeType* parSubtree ); + static size_type find_max_depth ( const NodeType* parSubtree ) { return FindMaxDepth_rec(parSubtree) - 1; } + static size_type find_max_depth_rec ( const NodeType* parSubtree ); #endif NodeType* m_root; From 62b22c42888a0f4d93d18f538b4fe68c0e54cb7e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 13 Aug 2020 21:35:53 +0100 Subject: [PATCH 05/60] Add copyright notice to scapegoat tree files --- include/duckhandy/implem/scapegoat_map.inl | 17 +++++++++++++++++ include/duckhandy/implem/scapegoat_tree.inl | 17 +++++++++++++++++ include/duckhandy/implem/tree_iterator.inl | 17 +++++++++++++++++ include/duckhandy/log2_fast.hpp | 17 +++++++++++++++++ include/duckhandy/scapegoat_map.hpp | 17 +++++++++++++++++ include/duckhandy/scapegoat_tree.hpp | 17 +++++++++++++++++ include/duckhandy/tree_iterator.hpp | 17 +++++++++++++++++ 7 files changed, 119 insertions(+) diff --git a/include/duckhandy/implem/scapegoat_map.inl b/include/duckhandy/implem/scapegoat_map.inl index 971668c..945a32e 100644 --- a/include/duckhandy/implem/scapegoat_map.inl +++ b/include/duckhandy/implem/scapegoat_map.inl @@ -1,3 +1,20 @@ +/* Copyright 2016-2020 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- diff --git a/include/duckhandy/implem/scapegoat_tree.inl b/include/duckhandy/implem/scapegoat_tree.inl index 6095fc7..690f650 100644 --- a/include/duckhandy/implem/scapegoat_tree.inl +++ b/include/duckhandy/implem/scapegoat_tree.inl @@ -1,3 +1,20 @@ +/* Copyright 2016-2020 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- diff --git a/include/duckhandy/implem/tree_iterator.inl b/include/duckhandy/implem/tree_iterator.inl index f4d9507..8425641 100644 --- a/include/duckhandy/implem/tree_iterator.inl +++ b/include/duckhandy/implem/tree_iterator.inl @@ -1,3 +1,20 @@ +/* Copyright 2016-2020 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + namespace duckmem { namespace Implem { ///--------------------------------------------------------------------- diff --git a/include/duckhandy/log2_fast.hpp b/include/duckhandy/log2_fast.hpp index 65e5d6a..b949843 100644 --- a/include/duckhandy/log2_fast.hpp +++ b/include/duckhandy/log2_fast.hpp @@ -1,3 +1,20 @@ +/* Copyright 2016-2020 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + #ifndef id28695193476D4A9499151FC175A49196 #define id28695193476D4A9499151FC175A49196 diff --git a/include/duckhandy/scapegoat_map.hpp b/include/duckhandy/scapegoat_map.hpp index e0010fa..22c62e4 100644 --- a/include/duckhandy/scapegoat_map.hpp +++ b/include/duckhandy/scapegoat_map.hpp @@ -1,3 +1,20 @@ +/* Copyright 2016-2020 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + #ifndef idDD2D1A57ABEB4BEEA0F7E46C347D1637 #define idDD2D1A57ABEB4BEEA0F7E46C347D1637 diff --git a/include/duckhandy/scapegoat_tree.hpp b/include/duckhandy/scapegoat_tree.hpp index 362e07a..f653d18 100644 --- a/include/duckhandy/scapegoat_tree.hpp +++ b/include/duckhandy/scapegoat_tree.hpp @@ -1,3 +1,20 @@ +/* Copyright 2016-2020 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + #ifndef id79CEDB2530B54204A6BEDCBE0B767EA1 #define id79CEDB2530B54204A6BEDCBE0B767EA1 diff --git a/include/duckhandy/tree_iterator.hpp b/include/duckhandy/tree_iterator.hpp index 258d3a9..babad3f 100644 --- a/include/duckhandy/tree_iterator.hpp +++ b/include/duckhandy/tree_iterator.hpp @@ -1,3 +1,20 @@ +/* Copyright 2016-2020 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + #ifndef id6109D5EDE99D43C4909F084A231BF2C2 #define id6109D5EDE99D43C4909F084A231BF2C2 From e61832f7cd1d7fa2a2301056fcc9d79931d86254 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 13 Aug 2020 22:58:35 +0100 Subject: [PATCH 06/60] Add erase test for scapegoat tree. Fix build as needed, implement find(). --- include/duckhandy/implem/scapegoat_tree.inl | 32 +++++++++-- include/duckhandy/implem/tree_iterator.inl | 4 +- include/duckhandy/scapegoat_tree.hpp | 4 +- test/unit/scapegoat_tree_test.cpp | 63 +++++++++++++++++++++ 4 files changed, 95 insertions(+), 8 deletions(-) diff --git a/include/duckhandy/implem/scapegoat_tree.inl b/include/duckhandy/implem/scapegoat_tree.inl index 690f650..b4fb8d9 100644 --- a/include/duckhandy/implem/scapegoat_tree.inl +++ b/include/duckhandy/implem/scapegoat_tree.inl @@ -559,7 +559,7 @@ namespace duckmem { ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- template - typename ScapegoatTree::NodeType* ScapegoatTree::find_ifp (const NodeType* parTree, const K& parKey) { + typename ScapegoatTree::NodeType* ScapegoatTree::find_ifp (NodeType* parTree, const K& parKey) { while (parTree) { if (parKey < parTree->content) parTree = parTree->left; @@ -632,7 +632,7 @@ namespace duckmem { ///------------------------------------------------------------------------- template bool ScapegoatTree::include (const K& parSearch) const { - const NodeType* const found = FindIFP(m_root, parSearch); + const NodeType* const found = find_ifp(m_root, parSearch); Assert(not found or not (parSearch < found->content or found->content < parSearch)); return static_cast(NULL != found); } @@ -654,7 +654,7 @@ namespace duckmem { ///------------------------------------------------------------------------- template void ScapegoatTree::erase (iterator parItem) { - NodeType* const dele = parItem->GetPointer(); + NodeType* const dele = parItem.GetPointer(); AssertRelease(NULL != dele); Assert(m_count > 0); @@ -662,7 +662,7 @@ namespace duckmem { if (dele == m_root) parent = m_root; else - parent = FindParentIFP(m_root, dele); + parent = find_parent_ifp(m_root, dele); Assert(NULL != parent); if (parent) { @@ -675,7 +675,7 @@ namespace duckmem { parentChildRef = (dele->left ? dele->left : dele->right); } else { - NodeType* const inorderSuccessor = DetachBottomNode(dele, true); + NodeType* const inorderSuccessor = detach_bottom_node(dele, true); parentChildRef = inorderSuccessor; inorderSuccessor->left = dele->left; @@ -689,6 +689,28 @@ namespace duckmem { rebalance_after_deletion_ifn(); } + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + inline typename ScapegoatTree::iterator ScapegoatTree::find (const K& parSearch) { + NodeStack stack; + const size_type depthHint = get_max_balanced_depth(std::max(m_reserved, m_count + 1), m_alphainvloginv) + 3; + stack.reserve(depthHint); + NodeType* const closestMatch = get_insert_parent(m_root, parSearch, stack); + Assert(stack.size() <= depthHint); + if (closestMatch->content == parSearch) + return iterator(stack.begin(), stack.size(), depthHint); + else + return this->end(); + } + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + template + inline typename ScapegoatTree::const_iterator ScapegoatTree::find (const K& parSearch) const { + return const_cast*>(this)->find(parSearch); + } + // ///------------------------------------------------------------------------- // ///------------------------------------------------------------------------- // template diff --git a/include/duckhandy/implem/tree_iterator.inl b/include/duckhandy/implem/tree_iterator.inl index 8425641..e3ad5dc 100644 --- a/include/duckhandy/implem/tree_iterator.inl +++ b/include/duckhandy/implem/tree_iterator.inl @@ -44,9 +44,9 @@ namespace duckmem { std::vector

localCopy; localCopy.reserve(parOther.m_stack.size()); while (not otherStackCopy.empty()) { - P convertedItem = otherStackCopy.top(); + P convertedItem = otherStackCopy.back(); localCopy.push_back(convertedItem); - otherStackCopy.pop(); + otherStackCopy.pop_back(); } m_stack.reserve(parOther.m_stack.capacity()); for (typename std::vector

::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) { diff --git a/include/duckhandy/scapegoat_tree.hpp b/include/duckhandy/scapegoat_tree.hpp index f653d18..6b44caf 100644 --- a/include/duckhandy/scapegoat_tree.hpp +++ b/include/duckhandy/scapegoat_tree.hpp @@ -117,6 +117,8 @@ namespace duckmem { void erase ( iterator parItem ); void erase ( iterator parFrom, iterator parLast ); size_type erase ( const value_type& parKey ); + iterator find ( const K& parSearch ); + const_iterator find ( const K& parSearch ) const; iterator begin ( void ); const_iterator begin ( void ) const; @@ -127,7 +129,7 @@ namespace duckmem { template static T* find_closest_match ( T* parTree, const K& parKey ); static NodeType* get_insert_parent ( NodeType* parTree, const K& parKey, NodeStack& parRewind ); - static NodeType* find_ifp ( const NodeType* parTree, const K& parKey ); + static NodeType* find_ifp ( NodeType* parTree, const K& parKey ); static NodeType* find_parent_ifp ( NodeType* parTree, const NodeType* parSearchNodeAddr ); static NodeType* get_new_node ( const K& parKey ); static void delete_nodes ( NodeType* parNode ); diff --git a/test/unit/scapegoat_tree_test.cpp b/test/unit/scapegoat_tree_test.cpp index cf531b8..3ec1217 100644 --- a/test/unit/scapegoat_tree_test.cpp +++ b/test/unit/scapegoat_tree_test.cpp @@ -17,6 +17,7 @@ #include "catch2/catch.hpp" #include "duckhandy/scapegoat_tree.hpp" +#include TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") { using duckmem::ScapegoatTree; @@ -87,3 +88,65 @@ TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][conta } } +TEST_CASE ("Erase values from a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") { + using duckmem::ScapegoatTree; + + //auto rand_num = std::bind(std::uniform_int_distribution(1, 1000), std::mt19937(std::time(0))); + + ScapegoatTree tree; + for (int z = 0; z < 5000; ++z) { + tree.insert(z + 1); + } + CHECK(tree.size() == 5000); + + std::set cpy(tree.begin(), tree.end()); + CHECK(cpy.size() == 5000); + + { + auto it_num = tree.find(0); + CHECK(it_num == tree.end()); + } + { + auto it_num = tree.find(1); + REQUIRE(it_num != tree.end()); + CHECK(*it_num == 1); + CHECK(it_num == tree.begin()); + tree.erase(it_num); + cpy.erase(1); + CHECK(tree.size() == 4999); + it_num = tree.find(1); + CHECK(it_num == tree.end()); + CHECK(not tree.include(1)); + } + { + auto it_num = tree.find(2345); + REQUIRE(it_num != tree.end()); + CHECK(*it_num == 2345); + tree.erase(it_num); + cpy.erase(2345); + CHECK(tree.size() == 4998); + it_num = tree.find(2345); + CHECK(it_num == tree.end()); + CHECK(not tree.include(2345)); + } + { + auto it_num = tree.find(3000); + REQUIRE(it_num != tree.end()); + int test_num = 3000; + for (; it_num != tree.end(); ++it_num) { + CHECK(*it_num == test_num); + test_num++; + } + CHECK(test_num == 5001); + } + { + const ScapegoatTree& ref = tree; + auto it_num = ref.find(18); + REQUIRE(it_num != ref.end()); + CHECK(*it_num == 18); + CHECK(ref.include(18)); + } + + REQUIRE(tree.size() == cpy.size()); + CHECK(std::equal(tree.begin(), tree.end(), cpy.begin())); +} From 79ca881bc1120a1ee038f4ef58fe23ffea602f47 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 13 Aug 2020 23:54:06 +0100 Subject: [PATCH 07/60] Warning fix This fixes ary_to_int() for negative values --- include/duckhandy/implem/int_conv.hpp | 16 ++++++++-------- test/unit/int_conv_test.cpp | 5 +++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index d7048ec..7d717be 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -166,6 +166,13 @@ namespace dhandy { } }; + template + [[gnu::always_inline,gnu::pure]] + inline T negated_ifn (T n, bool negate) { + //return static_cast(((static_cast(n) - (mask bitand 1)) xor mask) bitor ((mask bitand 1) << 31)); + return (negate ? -n : n); + } + template struct AryConversion { template @@ -183,7 +190,7 @@ namespace dhandy { retval += Tr::from_digit(beg[i]) * factor; factor *= Base; } - return retval; + return negated_ifn(retval, was_negative); } }; @@ -204,13 +211,6 @@ namespace dhandy { } }; - template - [[gnu::always_inline,gnu::pure]] - inline T negated_ifn (T n, bool negate) { - //return static_cast(((static_cast(n) - (mask bitand 1)) xor mask) bitor ((mask bitand 1) << 31)); - return (negate ? -n : n); - } - template [[gnu::pure]] T to_integer_sse (const C* s, std::size_t l) { diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index 9b947f3..26be172 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -155,4 +155,9 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { AryConversionTestHelper("7fffffff", 0x7fffffff); AryConversionTestHelper("1", true); AryConversionTestHelper("0", false); + + AryConversionTestHelper("-1", -1); + AryConversionTestHelper("-50000", -50000); + AryConversionTestHelper("-1", -1); + AryConversionTestHelper("-510123123123", -510123123123); } From f1d6ac789e34af3e9cefa572355b1613b4e23823 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 14 Aug 2020 00:04:05 +0100 Subject: [PATCH 08/60] Indentation --- include/duckhandy/int_conv.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index 2f63722..cbd557d 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -31,7 +31,7 @@ namespace dhandy { template struct IntConv, std::string>, F> { static std::string conv (const F& in) { - auto retval = dhandy::int_to_ary(in); + auto retval = dhandy::int_to_ary(in); return std::string(retval.begin(), retval.end() - 1); } }; From 1c6de14cd466ea067d5543de635a64ec0739b78e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 14 Aug 2020 00:30:22 +0100 Subject: [PATCH 09/60] Add test for upper case conversions and fix as necessary --- include/duckhandy/implem/int_conv.hpp | 2 +- test/unit/int_conv_test.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 7d717be..276238d 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -286,7 +286,7 @@ namespace dhandy { } }; template - using ASCIITranslatorUpcase = ASCIITranslator; + using ASCIITranslatorUpcase = ASCIITranslator; template > constexpr inline auto int_to_ary (I in) { diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index 26be172..6145328 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -34,6 +34,12 @@ namespace { using AryConversion = dhandy::implem::AryConversion>; CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); } + + template + void AryConversionTestHelperUp (const std::string_view& s, T expected) { + using AryConversion = dhandy::implem::AryConversion>; + CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); + } } //unnamed namespace TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") { @@ -74,6 +80,7 @@ TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") { CHECK(int_to_ary(-1) == "-1"); CHECK(int_to_ary(0x1000000000000000) == "1152921504606846976"); CHECK(int_to_ary(0xF000000000000000) == "-1152921504606846976"); + CHECK(int_to_ary>(255) == "FF"); CHECK(int_to_ary(0xFFFF) == "ffff"); CHECK(int_to_ary(0xCACA) == "caca"); @@ -155,6 +162,7 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { AryConversionTestHelper("7fffffff", 0x7fffffff); AryConversionTestHelper("1", true); AryConversionTestHelper("0", false); + AryConversionTestHelperUp("ABCDEF123456ABCD", 0xabcdef123456abcd); AryConversionTestHelper("-1", -1); AryConversionTestHelper("-50000", -50000); From 40bae9c49da15f439f0f855e9a9d1d31e7c654cf Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 02:59:51 +0200 Subject: [PATCH 10/60] Build fix for clang --- include/duckhandy/implem/int_conv.hpp | 2 +- include/duckhandy/string_bt.hpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 276238d..27a2386 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -195,7 +195,7 @@ namespace dhandy { }; template ::value and not std::is_same::value and sizeof(I) <= sizeof(uint32_t)>::type> - using SelectIForSSEToInt = I; + struct SelectIForSSEToInt; template struct AryConversion, Base, Tr> { diff --git a/include/duckhandy/string_bt.hpp b/include/duckhandy/string_bt.hpp index f4962d2..e6f6be3 100644 --- a/include/duckhandy/string_bt.hpp +++ b/include/duckhandy/string_bt.hpp @@ -63,6 +63,11 @@ namespace dhandy { const value_type m_data[S]; }; + template + constexpr auto string::operator[] (std::size_t parIndex) const -> value_type { + return (parIndex < S ? m_data[parIndex] : throw std::out_of_range("")); + } + namespace implem { template constexpr string concat ( const index_seq&, const string& parLeft, const string& parRight ) { @@ -108,11 +113,6 @@ namespace dhandy { return parStream; } - template - constexpr auto string::operator[] (std::size_t parIndex) const -> value_type { - return (parIndex < S ? m_data[parIndex] : throw std::out_of_range("")); - } - template constexpr string make_string (const Ch (&parData)[S]) { return string(parData); From 3343b51a39ff224160e75276c219478b54ad9d32 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 03:09:31 +0200 Subject: [PATCH 11/60] Simplify code --- include/duckhandy/implem/int_conv.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 27a2386..db9aa20 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -173,7 +173,7 @@ namespace dhandy { return (negate ? -n : n); } - template + template struct AryConversion { template static I from_ary (const C* beg, const C* end) { @@ -194,16 +194,13 @@ namespace dhandy { } }; - template ::value and not std::is_same::value and sizeof(I) <= sizeof(uint32_t)>::type> - struct SelectIForSSEToInt; - template - struct AryConversion, Base, Tr> { + struct AryConversion::value and not std::is_same::value and sizeof(I) <= sizeof(uint32_t)>::type> { template static I from_ary (C* beg, C* end) { return to_integer_sse(beg, end - beg); } }; template - struct AryConversion { + struct AryConversion { template static bool from_ary (C* beg, C* end) { if (end == beg) return false; From 93d2ad6bd0161ee577b49de463b5e1d65ea6f92e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 13:02:51 +0200 Subject: [PATCH 12/60] Make ary_to_int() constexpr --- CMakeLists.txt | 2 +- include/duckhandy/implem/int_conv.hpp | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43607b7..0621e5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ target_compile_features(${PROJECT_NAME} INTERFACE cxx_decltype_incomplete_return_types INTERFACE cxx_noexcept INTERFACE cxx_rvalue_references - INTERFACE cxx_std_17 + INTERFACE cxx_std_20 ) target_include_directories(${PROJECT_NAME} diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index db9aa20..9d941c6 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -33,6 +33,7 @@ # include # include #endif +#include namespace dhandy { namespace implem { @@ -168,15 +169,15 @@ namespace dhandy { template [[gnu::always_inline,gnu::pure]] - inline T negated_ifn (T n, bool negate) { + constexpr inline T negated_ifn (T n, bool negate) { //return static_cast(((static_cast(n) - (mask bitand 1)) xor mask) bitor ((mask bitand 1) << 31)); return (negate ? -n : n); } - template + template struct AryConversion { template - static I from_ary (const C* beg, const C* end) { + constexpr static I from_ary (const C* beg, const C* end) { I retval = 0; I factor = 1; std::size_t i = end - beg; @@ -195,13 +196,13 @@ namespace dhandy { }; template - struct AryConversion::value and not std::is_same::value and sizeof(I) <= sizeof(uint32_t)>::type> { + struct AryConversion::value and not std::is_same::value and sizeof(I) <= sizeof(uint32_t)>::type> { template static I from_ary (C* beg, C* end) { return to_integer_sse(beg, end - beg); } }; - template - struct AryConversion { - template static bool from_ary (C* beg, C* end) { + template + struct AryConversion { + template constexpr static bool from_ary (C* beg, C* end) { if (end == beg) return false; return (Tr::from_digit(*beg) ? true : false); @@ -291,8 +292,11 @@ namespace dhandy { } template > - inline R ary_to_int (const C* beg, const C* end) { - return implem::AryConversion::from_ary(beg, end); + constexpr inline R ary_to_int (const C* beg, const C* end) { + if (std::is_constant_evaluated()) + return implem::AryConversion::from_ary(beg, end); + else + return implem::AryConversion::from_ary(beg, end); } #if !defined(INT_CONV_WITHOUT_HELPERS) From da136cd52f0d2af46a3e5ce9ff7552ba52969233 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 13:14:10 +0200 Subject: [PATCH 13/60] Build fix in unit test --- test/unit/int_conv_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index 6145328..eed46a1 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -31,13 +31,13 @@ template using int_info_2 = dhandy::implem::int_info; namespace { template void AryConversionTestHelper (const std::string_view& s, T expected) { - using AryConversion = dhandy::implem::AryConversion>; + using AryConversion = dhandy::implem::AryConversion, false>; CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); } template void AryConversionTestHelperUp (const std::string_view& s, T expected) { - using AryConversion = dhandy::implem::AryConversion>; + using AryConversion = dhandy::implem::AryConversion, false>; CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); } } //unnamed namespace From 31245483143fedb46a84d823f3fa904d535d9bf5 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 13:34:05 +0200 Subject: [PATCH 14/60] Implement Version class --- include/duckhandy/version_bt.hpp | 101 +++++++++++++++++++++++++++++++ test/unit/CMakeLists.txt | 1 + test/unit/version_test.cpp | 94 ++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 include/duckhandy/version_bt.hpp create mode 100644 test/unit/version_test.cpp diff --git a/include/duckhandy/version_bt.hpp b/include/duckhandy/version_bt.hpp new file mode 100644 index 0000000..5b7f80d --- /dev/null +++ b/include/duckhandy/version_bt.hpp @@ -0,0 +1,101 @@ +/* Copyright 2016-2021 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#ifndef id5594416333AA4792BFEC94E863E03B08 +#define id5594416333AA4792BFEC94E863E03B08 + +#include "int_conv.hpp" +#include +#include + +namespace dhandy { + +template +class Version { +public: + constexpr static std::size_t Count = N; + + constexpr Version (const char* const ver, bool accept_less=false); + + constexpr unsigned int operator[] (std::size_t idx) const; + constexpr unsigned int major() const; + constexpr unsigned int minor() const; + constexpr unsigned int revision() const; + +private: + unsigned int m_versions[N]; +}; + +template +inline constexpr Version::Version (const char* const ver, bool accept_less) : + m_versions{0} +{ + std::size_t z = 0; + std::size_t s = 0; + std::size_t idx = 0; + bool commit = false; + + do { + if (ver[z] >= '0' and ver[z] <= '9') { + commit = true; + } + else if (commit) { + commit = false; + m_versions[idx++] = dhandy::ary_to_int(ver + s, ver + z); + s = z + 1; + } + else { + s = z + 1; + } + } while(ver[z++] and idx < N); + + if (not accept_less and idx < N) + throw std::invalid_argument("Input version doesn't contain enough version numbers"); +} + +template +inline constexpr unsigned int Version::operator[] (std::size_t idx) const { + if (idx < N) + return m_versions[idx]; + else + throw std::out_of_range("Index is out of range"); +} + +template +inline constexpr unsigned int Version::major() const { + return m_versions[0]; +} + +template +inline constexpr unsigned int Version::minor() const { + if constexpr (N > 1) + return m_versions[1]; + else + throw std::out_of_range("Not enough version entries, there is no minor number"); +} + +template +inline constexpr unsigned int Version::revision() const { + if constexpr (N > 2) + return m_versions[2]; + else + throw std::out_of_range("Not enough version entries, there is no revision number"); +} + +} //namespace dhandy + +#endif diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index eaae1f8..16efbcf 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable(${PROJECT_NAME} reversed_sized_array_test.cpp bitfield_pack_test.cpp resource_pool_test.cpp + version_test.cpp ) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/test/unit/version_test.cpp b/test/unit/version_test.cpp new file mode 100644 index 0000000..60b8cb0 --- /dev/null +++ b/test/unit/version_test.cpp @@ -0,0 +1,94 @@ +/* Copyright 2016-2021 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#include "catch2/catch.hpp" +#include "duckhandy/version_bt.hpp" + +TEST_CASE ("Version class tests", "[version][bt]") { + using dhandy::Version; + + { + constexpr Version<1> ver{"102"}; + static_assert(ver.major() == 102, "Version error"); + static_assert(ver.Count == 1, "Version error"); + CHECK(ver[0] == 102); + CHECK_THROWS(ver[1]); + CHECK_THROWS(ver[2]); + CHECK_THROWS(ver[3]); + CHECK_THROWS(ver[4]); + } + + { + constexpr Version<3> ver{".aheud15,a.ud22,cu.sh81,.nuad.h44"}; + static_assert(ver.Count == 3, "Version error"); + static_assert(ver.major() == 15, "Version error"); + static_assert(ver.minor() == 22, "Version error"); + static_assert(ver.revision() == 81, "Version error"); + CHECK(ver[0] == 15); + CHECK(ver[1] == 22); + CHECK(ver[2] == 81); + CHECK_THROWS(ver[3]); + CHECK_THROWS(ver[4]); + } + + { + constexpr Version<10> ver{"1.2.3.44.55.66.777.888.999.101010"}; + static_assert(ver.Count == 10, "Version error"); + static_assert(ver.major() == 1, "Version error"); + static_assert(ver.minor() == 2, "Version error"); + static_assert(ver.revision() == 3, "Version error"); + CHECK(ver[0] == 1); + CHECK(ver[1] == 2); + CHECK(ver[2] == 3); + CHECK(ver[3] == 44); + CHECK(ver[4] == 55); + CHECK(ver[5] == 66); + CHECK(ver[6] == 777); + CHECK(ver[7] == 888); + CHECK(ver[8] == 999); + CHECK(ver[9] == 101010); + CHECK_THROWS(ver[10]); + } + + { + constexpr Version<4> ver{"1.2.3.", true}; + static_assert(ver.Count == 4, "Version error"); + static_assert(ver.major() == 1, "Version error"); + static_assert(ver.minor() == 2, "Version error"); + static_assert(ver.revision() == 3, "Version error"); + CHECK(ver[0] == 1); + CHECK(ver[1] == 2); + CHECK(ver[2] == 3); + CHECK(ver[3] == 0); + CHECK_THROWS(ver[10]); + } + + { + constexpr Version<4> ver{"6.7.2-r1"}; + static_assert(ver.Count == 4, "Version error"); + static_assert(ver.major() == 6, "Version error"); + static_assert(ver.minor() == 7, "Version error"); + static_assert(ver.revision() == 2, "Version error"); + CHECK(ver[0] == 6); + CHECK(ver[1] == 7); + CHECK(ver[2] == 2); + CHECK(ver[3] == 1); + CHECK_THROWS(ver[10]); + } + + CHECK_THROWS(Version<4>{"4.5"}); +} From 13bd166827623ea80a71bfb0749647f19886eb12 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 13:35:37 +0200 Subject: [PATCH 15/60] Rename Count to lowercase, make const --- include/duckhandy/version_bt.hpp | 2 +- test/unit/version_test.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/duckhandy/version_bt.hpp b/include/duckhandy/version_bt.hpp index 5b7f80d..ebabbc0 100644 --- a/include/duckhandy/version_bt.hpp +++ b/include/duckhandy/version_bt.hpp @@ -27,7 +27,7 @@ namespace dhandy { template class Version { public: - constexpr static std::size_t Count = N; + constexpr static const std::size_t count = N; constexpr Version (const char* const ver, bool accept_less=false); diff --git a/test/unit/version_test.cpp b/test/unit/version_test.cpp index 60b8cb0..3f69ace 100644 --- a/test/unit/version_test.cpp +++ b/test/unit/version_test.cpp @@ -24,7 +24,7 @@ TEST_CASE ("Version class tests", "[version][bt]") { { constexpr Version<1> ver{"102"}; static_assert(ver.major() == 102, "Version error"); - static_assert(ver.Count == 1, "Version error"); + static_assert(ver.count == 1, "Version error"); CHECK(ver[0] == 102); CHECK_THROWS(ver[1]); CHECK_THROWS(ver[2]); @@ -34,7 +34,7 @@ TEST_CASE ("Version class tests", "[version][bt]") { { constexpr Version<3> ver{".aheud15,a.ud22,cu.sh81,.nuad.h44"}; - static_assert(ver.Count == 3, "Version error"); + static_assert(ver.count == 3, "Version error"); static_assert(ver.major() == 15, "Version error"); static_assert(ver.minor() == 22, "Version error"); static_assert(ver.revision() == 81, "Version error"); @@ -47,7 +47,7 @@ TEST_CASE ("Version class tests", "[version][bt]") { { constexpr Version<10> ver{"1.2.3.44.55.66.777.888.999.101010"}; - static_assert(ver.Count == 10, "Version error"); + static_assert(ver.count == 10, "Version error"); static_assert(ver.major() == 1, "Version error"); static_assert(ver.minor() == 2, "Version error"); static_assert(ver.revision() == 3, "Version error"); @@ -66,7 +66,7 @@ TEST_CASE ("Version class tests", "[version][bt]") { { constexpr Version<4> ver{"1.2.3.", true}; - static_assert(ver.Count == 4, "Version error"); + static_assert(ver.count == 4, "Version error"); static_assert(ver.major() == 1, "Version error"); static_assert(ver.minor() == 2, "Version error"); static_assert(ver.revision() == 3, "Version error"); @@ -79,7 +79,7 @@ TEST_CASE ("Version class tests", "[version][bt]") { { constexpr Version<4> ver{"6.7.2-r1"}; - static_assert(ver.Count == 4, "Version error"); + static_assert(ver.count == 4, "Version error"); static_assert(ver.major() == 6, "Version error"); static_assert(ver.minor() == 7, "Version error"); static_assert(ver.revision() == 2, "Version error"); From 1f44e74465d2c41fbbb11dfff8f2a22564215793 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 13:44:49 +0200 Subject: [PATCH 16/60] Test if conversion is using the sse when possible --- include/duckhandy/implem/int_conv.hpp | 7 ++- test/unit/int_conv_test.cpp | 66 ++++++++++++++------------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 9d941c6..7285b57 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,8 @@ namespace dhandy { template struct AryConversion { + constexpr static const bool is_sse = false; + template constexpr static I from_ary (const C* beg, const C* end) { I retval = 0; @@ -196,12 +199,14 @@ namespace dhandy { }; template - struct AryConversion::value and not std::is_same::value and sizeof(I) <= sizeof(uint32_t)>::type> { + struct AryConversion::value and not std::is_same::value and sizeof(I) <= sizeof(std::uint32_t)>::type> { + constexpr static const bool is_sse = true; template static I from_ary (C* beg, C* end) { return to_integer_sse(beg, end - beg); } }; template struct AryConversion { + constexpr static const bool is_sse = false; template constexpr static bool from_ary (C* beg, C* end) { if (end == beg) return false; diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index eed46a1..7d1055b 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -30,14 +30,16 @@ template using int_info_2 = dhandy::implem::int_info; namespace { template - void AryConversionTestHelper (const std::string_view& s, T expected) { + void AryConversionTestHelper (const std::string_view& s, T expected, bool expect_sse) { using AryConversion = dhandy::implem::AryConversion, false>; + CHECK(AryConversion::is_sse == expect_sse); CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); } template - void AryConversionTestHelperUp (const std::string_view& s, T expected) { + void AryConversionTestHelperUp (const std::string_view& s, T expected, bool expect_sse) { using AryConversion = dhandy::implem::AryConversion, false>; + CHECK(AryConversion::is_sse == expect_sse); CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); } } //unnamed namespace @@ -137,35 +139,35 @@ TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") { } TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { - AryConversionTestHelper("0", 0); - AryConversionTestHelper("0", 0); - AryConversionTestHelper("0", 0); - AryConversionTestHelper("ff", 0xff); - AryConversionTestHelper("ff", 0xff); - AryConversionTestHelper("rs", 1000); - AryConversionTestHelper("20", 16); - AryConversionTestHelper("1", 1); - AryConversionTestHelper("10", 10); - AryConversionTestHelper("100", 100); - AryConversionTestHelper("999", 999); - AryConversionTestHelper("1000", 1000); - AryConversionTestHelper("1001", 1001); - AryConversionTestHelper("12345", 12345); - AryConversionTestHelper("123456", 123456); - AryConversionTestHelper("1234567", 1234567); - AryConversionTestHelper("12345678", 12345678); - AryConversionTestHelper("123456789", 123456789); - AryConversionTestHelper("2147483647", 2147483647); - AryConversionTestHelper("ffffffffffffffff", 0xffffffffffffffff); - AryConversionTestHelper("ffffffffffffffff", 0xffffffffffffffff); - AryConversionTestHelper("7fffffffffffffff", 0x7fffffffffffffff); - AryConversionTestHelper("7fffffff", 0x7fffffff); - AryConversionTestHelper("1", true); - AryConversionTestHelper("0", false); - AryConversionTestHelperUp("ABCDEF123456ABCD", 0xabcdef123456abcd); + AryConversionTestHelper("0", 0, true); + AryConversionTestHelper("0", 0, true); + AryConversionTestHelper("0", 0, true); + AryConversionTestHelper("ff", 0xff, true); + AryConversionTestHelper("ff", 0xff, true); + AryConversionTestHelper("rs", 1000, true); + AryConversionTestHelper("20", 16, true); + AryConversionTestHelper("1", 1, true); + AryConversionTestHelper("10", 10, true); + AryConversionTestHelper("100", 100, true); + AryConversionTestHelper("999", 999, true); + AryConversionTestHelper("1000", 1000, true); + AryConversionTestHelper("1001", 1001, true); + AryConversionTestHelper("12345", 12345, true); + AryConversionTestHelper("123456", 123456, true); + AryConversionTestHelper("1234567", 1234567, true); + AryConversionTestHelper("12345678", 12345678, true); + AryConversionTestHelper("123456789", 123456789, true); + AryConversionTestHelper("2147483647", 2147483647, true); + AryConversionTestHelper("ffffffffffffffff", 0xffffffffffffffff, false); + AryConversionTestHelper("ffffffffffffffff", 0xffffffffffffffff, false); + AryConversionTestHelper("7fffffffffffffff", 0x7fffffffffffffff, false); + AryConversionTestHelper("7fffffff", 0x7fffffff, true); + AryConversionTestHelper("1", true, false); + AryConversionTestHelper("0", false, false); + AryConversionTestHelperUp("ABCDEF123456ABCD", 0xabcdef123456abcd, false); - AryConversionTestHelper("-1", -1); - AryConversionTestHelper("-50000", -50000); - AryConversionTestHelper("-1", -1); - AryConversionTestHelper("-510123123123", -510123123123); + AryConversionTestHelper("-1", -1, sizeof(signed int) <= sizeof(std::uint32_t)); + AryConversionTestHelper("-50000", -50000, sizeof(signed int) <= sizeof(std::uint32_t)); + AryConversionTestHelper("-1", -1, false); + AryConversionTestHelper("-510123123123", -510123123123, false); } From b52343014b9af3cafae8a695ec02f1678da69397 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 13:57:57 +0200 Subject: [PATCH 17/60] int_conv can be constexpr sometimes --- include/duckhandy/int_conv.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index cbd557d..a092046 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -43,14 +43,14 @@ namespace dhandy { }; template struct IntConv, std::string_view>> { - static T conv (const std::string_view& in) { + constexpr static T conv (const std::string_view& in) { return dhandy::ary_to_int(in.data(), in.data() + in.size()); } }; } //namespace implem template - inline To int_conv (const From& from) { + constexpr inline To int_conv (const From& from) { return implem::IntConv::conv(from); } } //namespace dhandy From 710cdf9f040f5a26b8d4d8d62c17f4b2fff46e2b Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 13:59:51 +0200 Subject: [PATCH 18/60] Allow string_view conv when it's safe You can still force a string_view conv even when it's not safe to do so if you only intend to use the return value during its lifetime validity. Call int_conv_temporary() in that case. --- include/duckhandy/int_conv.hpp | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index a092046..b455c9d 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -22,27 +22,37 @@ #include #include #include +#include namespace dhandy { namespace implem { - template + template struct IntConv; - template - struct IntConv, std::string>, F> { + template + struct IntConv, std::string>, F, SafeRetval> { static std::string conv (const F& in) { auto retval = dhandy::int_to_ary(in); return std::string(retval.begin(), retval.end() - 1); } }; - template - struct IntConv, std::string>> { - static T conv (const std::string& in) { + template + struct IntConv, std::string_view>, F, SafeRetval> { + constexpr static std::string_view conv (const F& in) { + if (std::is_constant_evaluated() or not SafeRetval) + return dhandy::int_to_ary(in).to_string_view(); + else + throw std::logic_error("Only callable in a constexpr context, call int_conv_temporary() instead if you know what you're doing"); + } + }; + template + struct IntConv, std::string>, SafeRetval> { + constexpr static T conv (const std::string& in) { return dhandy::ary_to_int(in.data(), in.data() + in.size()); } }; - template - struct IntConv, std::string_view>> { + template + struct IntConv, std::string_view>, SafeRetval> { constexpr static T conv (const std::string_view& in) { return dhandy::ary_to_int(in.data(), in.data() + in.size()); } @@ -51,7 +61,12 @@ namespace dhandy { template constexpr inline To int_conv (const From& from) { - return implem::IntConv::conv(from); + return implem::IntConv::conv(from); + } + + template + constexpr inline To int_conv_temporary (const From& from) { + return implem::IntConv::conv(from); } } //namespace dhandy From 5db217c9782e69254ed9fdab96efa56af13fd24a Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 14:07:53 +0200 Subject: [PATCH 19/60] Update copyright to 2021 --- include/duckhandy/MaxSizedArray.hpp | 2 +- include/duckhandy/bitfield_pack.hpp | 2 +- include/duckhandy/cmake_on_off.h | 2 +- include/duckhandy/compatibility.h | 2 +- include/duckhandy/ducktypes.hpp | 2 +- include/duckhandy/endianness.hpp | 2 +- include/duckhandy/implem/AutomemBase.hpp | 2 +- include/duckhandy/implem/AutomemBase.inl | 2 +- include/duckhandy/implem/IteratorOnPtr.hpp | 2 +- include/duckhandy/implem/int_conv.hpp | 2 +- include/duckhandy/implem/reversed_sized_array_bt.hpp | 2 +- include/duckhandy/int_conv.hpp | 2 +- include/duckhandy/int_types.hpp | 2 +- include/duckhandy/lengthof.h | 2 +- include/duckhandy/resource_pool.hpp | 2 +- include/duckhandy/sequence_bt.hpp | 2 +- include/duckhandy/string_bt.hpp | 2 +- include/duckhandy/stringize.h | 2 +- test/unit/bitfield_pack_test.cpp | 2 +- test/unit/endianness_test.cpp | 2 +- test/unit/int_conv_test.cpp | 2 +- test/unit/main.cpp | 2 +- test/unit/resource_pool_test.cpp | 2 +- test/unit/reversed_sized_array_test.cpp | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/duckhandy/MaxSizedArray.hpp b/include/duckhandy/MaxSizedArray.hpp index 8bdf2aa..5dda780 100644 --- a/include/duckhandy/MaxSizedArray.hpp +++ b/include/duckhandy/MaxSizedArray.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/bitfield_pack.hpp b/include/duckhandy/bitfield_pack.hpp index 2401e2e..a837587 100644 --- a/include/duckhandy/bitfield_pack.hpp +++ b/include/duckhandy/bitfield_pack.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/cmake_on_off.h b/include/duckhandy/cmake_on_off.h index d40f237..3daf77c 100644 --- a/include/duckhandy/cmake_on_off.h +++ b/include/duckhandy/cmake_on_off.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/compatibility.h b/include/duckhandy/compatibility.h index 9a472a1..5797cbf 100644 --- a/include/duckhandy/compatibility.h +++ b/include/duckhandy/compatibility.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/ducktypes.hpp b/include/duckhandy/ducktypes.hpp index 60b3791..58f9a06 100644 --- a/include/duckhandy/ducktypes.hpp +++ b/include/duckhandy/ducktypes.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/endianness.hpp b/include/duckhandy/endianness.hpp index 8ad30a8..af3dac4 100644 --- a/include/duckhandy/endianness.hpp +++ b/include/duckhandy/endianness.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/AutomemBase.hpp b/include/duckhandy/implem/AutomemBase.hpp index 104c996..ed45298 100644 --- a/include/duckhandy/implem/AutomemBase.hpp +++ b/include/duckhandy/implem/AutomemBase.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/AutomemBase.inl b/include/duckhandy/implem/AutomemBase.inl index 67b36bc..89c7148 100644 --- a/include/duckhandy/implem/AutomemBase.inl +++ b/include/duckhandy/implem/AutomemBase.inl @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/IteratorOnPtr.hpp b/include/duckhandy/implem/IteratorOnPtr.hpp index a060045..6f76ad7 100644 --- a/include/duckhandy/implem/IteratorOnPtr.hpp +++ b/include/duckhandy/implem/IteratorOnPtr.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 7285b57..5d9584c 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index 15caa78..a6904f2 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index b455c9d..a9fd3a7 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/int_types.hpp b/include/duckhandy/int_types.hpp index 25b39de..47bdc16 100644 --- a/include/duckhandy/int_types.hpp +++ b/include/duckhandy/int_types.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/lengthof.h b/include/duckhandy/lengthof.h index c60dd3d..650ab05 100644 --- a/include/duckhandy/lengthof.h +++ b/include/duckhandy/lengthof.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/resource_pool.hpp b/include/duckhandy/resource_pool.hpp index 5a1f560..e477e21 100644 --- a/include/duckhandy/resource_pool.hpp +++ b/include/duckhandy/resource_pool.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/sequence_bt.hpp b/include/duckhandy/sequence_bt.hpp index 53e617b..ee92e92 100644 --- a/include/duckhandy/sequence_bt.hpp +++ b/include/duckhandy/sequence_bt.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/string_bt.hpp b/include/duckhandy/string_bt.hpp index e6f6be3..a7f1862 100644 --- a/include/duckhandy/string_bt.hpp +++ b/include/duckhandy/string_bt.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/stringize.h b/include/duckhandy/stringize.h index e8b6abe..a805ad0 100644 --- a/include/duckhandy/stringize.h +++ b/include/duckhandy/stringize.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/bitfield_pack_test.cpp b/test/unit/bitfield_pack_test.cpp index 38e054f..04cc14e 100644 --- a/test/unit/bitfield_pack_test.cpp +++ b/test/unit/bitfield_pack_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/endianness_test.cpp b/test/unit/endianness_test.cpp index 42aae88..92902a9 100644 --- a/test/unit/endianness_test.cpp +++ b/test/unit/endianness_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index 7d1055b..ebbe445 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/main.cpp b/test/unit/main.cpp index 9931d36..f38d2a5 100644 --- a/test/unit/main.cpp +++ b/test/unit/main.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/resource_pool_test.cpp b/test/unit/resource_pool_test.cpp index 3620ec6..7821179 100644 --- a/test/unit/resource_pool_test.cpp +++ b/test/unit/resource_pool_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/reversed_sized_array_test.cpp b/test/unit/reversed_sized_array_test.cpp index 279ccb4..5ffc05f 100644 --- a/test/unit/reversed_sized_array_test.cpp +++ b/test/unit/reversed_sized_array_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2021 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify From 5ccf4dde55f5758cc8566619572688f11368a26d Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 14:08:13 +0200 Subject: [PATCH 20/60] Update Catch2 to latest v2.x branch --- lib/Catch2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Catch2 b/lib/Catch2 index 89f5f84..5c88067 160000 --- a/lib/Catch2 +++ b/lib/Catch2 @@ -1 +1 @@ -Subproject commit 89f5f8435176aad44624442b7f1e874a513bee67 +Subproject commit 5c88067bd339465513af4aec606bd2292f1b594a From eedad0d82cef505f938a2dc484837d1f48e5283e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 22 Apr 2021 14:10:28 +0200 Subject: [PATCH 21/60] Move Version to bt namespace --- include/duckhandy/version_bt.hpp | 4 ++-- test/unit/version_test.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/duckhandy/version_bt.hpp b/include/duckhandy/version_bt.hpp index ebabbc0..d29276b 100644 --- a/include/duckhandy/version_bt.hpp +++ b/include/duckhandy/version_bt.hpp @@ -22,7 +22,7 @@ #include #include -namespace dhandy { +namespace dhandy::bt { template class Version { @@ -96,6 +96,6 @@ inline constexpr unsigned int Version::revision() const { throw std::out_of_range("Not enough version entries, there is no revision number"); } -} //namespace dhandy +} //namespace dhandy::bt #endif diff --git a/test/unit/version_test.cpp b/test/unit/version_test.cpp index 3f69ace..cd6c86b 100644 --- a/test/unit/version_test.cpp +++ b/test/unit/version_test.cpp @@ -19,7 +19,7 @@ #include "duckhandy/version_bt.hpp" TEST_CASE ("Version class tests", "[version][bt]") { - using dhandy::Version; + using dhandy::bt::Version; { constexpr Version<1> ver{"102"}; From 29f6a56fc8f0b638fadecb5e4abc14ec194b4266 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 01:44:28 +0200 Subject: [PATCH 22/60] Some cleaning --- CMakeLists.txt | 1 - cmake/Modules/shared_git_project.cmake | 85 -------------------------- flat_git.yml | 2 - 3 files changed, 88 deletions(-) delete mode 100644 cmake/Modules/shared_git_project.cmake delete mode 100644 flat_git.yml diff --git a/CMakeLists.txt b/CMakeLists.txt index 0621e5e..846b275 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.8 FATAL_ERROR) project(duckhandy VERSION 0.1.0) list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) -include(shared_git_project) include(CTest) find_package(Sprout REQUIRED) diff --git a/cmake/Modules/shared_git_project.cmake b/cmake/Modules/shared_git_project.cmake deleted file mode 100644 index d494861..0000000 --- a/cmake/Modules/shared_git_project.cmake +++ /dev/null @@ -1,85 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12.2 FATAL_ERROR) - -function (add_shared_git_project SUBMODULE_PATH) - if (IS_ABSOLUTE "${SUBMODULE_PATH}") - set(submod_path "${SUBMODULE_PATH}") - else() - set(submod_path "${CMAKE_CURRENT_SOURCE_DIR}/${SUBMODULE_PATH}") - endif() - - if (NOT EXISTS "${submod_path}") - message(FATAL_ERROR "Path \"${submod_path}\" doesn't exist") - endif() - if (NOT IS_DIRECTORY "${submod_path}") - message(FATAL_ERROR "Path \"${submod_path}\" is not a valid directory") - endif() - - if (NOT EXISTS "${submod_path}/.git") - message(FATAL_ERROR ".git not found in \"${submod_path}\". Not a git submodule?") - endif() - if (IS_DIRECTORY "${submod_path}/.git") - message(FATAL_ERROR "\"${submod_path}.git\" is a directory, not a file as expected. Not a git submodule?") - endif() - - get_filename_component(proj_name_orig "${submod_path}" NAME) - if ("${proj_name_orig}" STREQUAL "") - message(FATAL_ERROR "Couldn't make up a name for given project in \"${submod_path}\"") - endif() - - string(MAKE_C_IDENTIFIER "${proj_name_orig}" proj_name_c_id) - string(TOUPPER ${proj_name_c_id} proj_name) - - get_property(shared_projects_list GLOBAL PROPERTY SHARED_PROJECTS_LIST) - list(FIND shared_projects_list ${proj_name} found_index) - if (${found_index} GREATER -1) - #nothing to do, the variable is already set so the project must have been - #included already - return() - endif() - - #Obtain the path to the working tree - # see http://stackoverflow.com/questions/27379818/git-possible-to-use-same-submodule-working-copy-by-multiple-projects - # git rev-parse --git-dir --show-toplevel - execute_process( - COMMAND git rev-parse --show-toplevel - WORKING_DIRECTORY "${submod_path}" - OUTPUT_VARIABLE matched_gitdir - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - #Make sure we got an absolute path - if (IS_ABSOLUTE "${matched_gitdir}") - set(reported_submodule_dir "${matched_gitdir}") - else() - file(RELATIVE_PATH reported_submodule_dir "${CMAKE_CURRENT_SOURCE_DIR}" "${submod_path}/${matched_gitdir}") - endif() - unset(matched_gitdir) - - #Check if submodule is a subdirectory of the current source dir - file(RELATIVE_PATH reported_submodule_rel_path "${CMAKE_CURRENT_SOURCE_DIR}" "${reported_submodule_dir}") - string(LENGTH "${reported_submodule_rel_path}" rel_path_len) - if (${rel_path_len} GREATER 2) - string(SUBSTRING "${reported_submodule_rel_path}" 0 3 first_bit) - if ("../" STREQUAL "${first_bit}") - set(is_out_of_dirtree ON) - else() - set(is_out_of_dirtree OFF) - endif() - unset(first_bit) - else() - set(is_out_of_dirtree OFF) - endif() - unset(rel_path_len) - - #Globally mark current submodule as handled - set_property(GLOBAL APPEND PROPERTY SHARED_PROJECTS_LIST ${proj_name}) - - set(shared_project_binary "${CMAKE_CURRENT_BINARY_DIR}/shared_projects/${proj_name_orig}") - if (is_out_of_dirtree) - #message(FATAL_ERROR "Would call add_subdirectory(\"${reported_submodule_dir}\" \"${shared_project_binary}\")") - add_subdirectory("${reported_submodule_dir}" "${shared_project_binary}" ${ARGN}) - else() - #message(FATAL_ERROR "Would call add_subdirectory(\"${reported_submodule_rel_path}\")") - add_subdirectory("${reported_submodule_rel_path}" ${ARGN}) - endif() -endfunction() diff --git a/flat_git.yml b/flat_git.yml deleted file mode 100644 index f653ae4..0000000 --- a/flat_git.yml +++ /dev/null @@ -1,2 +0,0 @@ -inplace_submodules: - - Sprout From 7f8f092372bbec06d84fc35327809430bae13ab7 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 01:44:49 +0200 Subject: [PATCH 23/60] Fix wrong variable name --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 846b275..1896d76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,9 +8,9 @@ find_package(Sprout REQUIRED) set(DUCKHANDY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") if (BUILD_TESTING) - set(BUILD_TESTS CACHE BOOL ON) + set(BUILD_TESTING CACHE BOOL ON) else() - set(BUILD_TESTS CACHE BOOL OFF) + set(BUILD_TESTING CACHE BOOL OFF) endif() add_library(${PROJECT_NAME} INTERFACE) From e62da38cf9c006bbe0ef18837476f7c832e16905 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 02:03:52 +0200 Subject: [PATCH 24/60] Cleaning up and simplifying code a bit --- include/duckhandy/implem/int_conv.hpp | 30 ++++++++++++++------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 5d9584c..d7c8782 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -70,6 +70,9 @@ namespace dhandy { static const constexpr std::size_t max_len = max_digit_count, I>::type, Base> + is_signed; }; + template + using RevArray = ReversedSizedArray::max_len + 1>; + template ::is_signed> struct IsNegative { static constexpr bool check (I) { return false; } }; template @@ -99,14 +102,13 @@ namespace dhandy { template struct IntConversion { - static constexpr ReversedSizedArray().to_digit(1))>, implem::int_info::max_len + 1> to_ary (I in) { - using RetType = ReversedSizedArray().to_digit(1))>, implem::int_info::max_len + 1>; + static constexpr RevArray to_ary (I in) { using Num = implem::NumberAdaptation; const bool was_negative = implem::is_negative(in); - RetType arr; - arr.push_front('\0'); + RevArray arr; + arr.push_front(Tr::NullChar); do { arr.push_front(Tr::to_digit(static_cast(Num::abs(Num::cast(in)) % Base))); in = static_cast(Num::cast(in) / static_cast(Base)); @@ -119,11 +121,9 @@ namespace dhandy { template struct IntConversion { - static constexpr ReversedSizedArray().to_digit(1))>, 2> to_ary (bool in) { - using RetType = ReversedSizedArray().to_digit(1))>, 2>; - - RetType arr; - arr.push_front('\0'); + static constexpr ReversedSizedArray to_ary (bool in) { + ReversedSizedArray arr; + arr.push_front(Tr::NullChar); arr.push_front(in ? Tr::to_digit(1) : Tr::to_digit(0)); return arr; } @@ -131,8 +131,8 @@ namespace dhandy { template struct IntConversion::value and not std::is_same::value>::type> { - static constexpr ReversedSizedArray().to_digit(1))>, implem::int_info::max_len + 1> to_ary (I in) { - using RetType = ReversedSizedArray().to_digit(1))>, implem::int_info::max_len + 1>; + static constexpr RevArray to_ary (I in) { + using RetType = RevArray; using Num = implem::NumberAdaptation; const constexpr char lookup[200] = { @@ -147,7 +147,7 @@ namespace dhandy { const bool was_negative = implem::is_negative(in); RetType arr; - arr.push_front('\0'); + arr.push_front(Tr::NullChar); while (Num::abs(in) >= static_cast(100)) { const auto index = (Num::abs(in) % 100) * 2; arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); @@ -266,13 +266,15 @@ namespace dhandy { } } //namespace implem - template + template struct ASCIITranslator { + typedef C char_type; static const constexpr bool BehavesLikeASCII = true; static const constexpr C FirstDigit = FDigit; static const constexpr C FirstLetter = FLetter; static const constexpr C Plus = CPlus; static const constexpr C Minus = CMinus; + static const constexpr C NullChar = CNull; static constexpr C to_digit (unsigned int num) { return (num <= 9 ? @@ -293,7 +295,7 @@ namespace dhandy { template > constexpr inline auto int_to_ary (I in) { - return implem::IntConversion, Base, Tr>::to_ary(in); + return implem::IntConversion, Base, Tr>::to_ary(in); } template > From 422b475ce3aa1da8d50ea29620ed221497cf7738 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 02:06:28 +0200 Subject: [PATCH 25/60] Add support for constexpr string_view creation --- include/duckhandy/implem/int_conv.hpp | 8 ++++ include/duckhandy/int_conv.hpp | 63 ++++++++++++++++++--------- test/unit/int_conv_test.cpp | 24 ++++++++++ 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index d7c8782..5dc8903 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -168,6 +168,9 @@ namespace dhandy { } }; + template + inline constexpr const auto g_int_to_str = IntConversion, Base, Tr>::to_ary(In); + template [[gnu::always_inline,gnu::pure]] constexpr inline T negated_ifn (T n, bool negate) { @@ -293,6 +296,11 @@ namespace dhandy { template using ASCIITranslatorUpcase = ASCIITranslator; + template > + constexpr inline const auto& buildtime_int_to_ary() { + return implem::g_int_to_str; + } + template > constexpr inline auto int_to_ary (I in) { return implem::IntConversion, Base, Tr>::to_ary(in); diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index a9fd3a7..6fb4b16 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -26,47 +26,68 @@ namespace dhandy { namespace implem { - template + template struct IntConv; - template - struct IntConv, std::string>, F, SafeRetval> { - static std::string conv (const F& in) { - auto retval = dhandy::int_to_ary(in); - return std::string(retval.begin(), retval.end() - 1); + template + using IntConvString = std::basic_string; + + template + using IntConvStringView = std::basic_string_view; + + template + struct IntConv, IntConvString>, F, SafeRetval, Tr> { + static IntConvString conv (const F& in) { + auto retval = dhandy::int_to_ary(in); + return IntConvString{retval.begin(), retval.end() - 1}; } }; - template - struct IntConv, std::string_view>, F, SafeRetval> { - constexpr static std::string_view conv (const F& in) { + template + struct IntConv, IntConvStringView>, F, SafeRetval, Tr> { + constexpr static IntConvStringView conv (const F& in) { if (std::is_constant_evaluated() or not SafeRetval) - return dhandy::int_to_ary(in).to_string_view(); + return dhandy::int_to_ary(in).to_string_view(); else throw std::logic_error("Only callable in a constexpr context, call int_conv_temporary() instead if you know what you're doing"); } }; - template - struct IntConv, std::string>, SafeRetval> { - constexpr static T conv (const std::string& in) { - return dhandy::ary_to_int(in.data(), in.data() + in.size()); + template + struct IntConv, IntConvString>, SafeRetval, Tr> { + constexpr static T conv (const IntConvString& in) { + return dhandy::ary_to_int( + in.data(), + in.data() + in.size() + ); } }; - template - struct IntConv, std::string_view>, SafeRetval> { - constexpr static T conv (const std::string_view& in) { - return dhandy::ary_to_int(in.data(), in.data() + in.size()); + template + struct IntConv, IntConvStringView>, SafeRetval, Tr> { + constexpr static T conv (const IntConvStringView& in) { + return dhandy::ary_to_int( + in.data(), + in.data() + in.size() + ); + } + }; + template + struct IntConv, SafeRetval, Tr> { + constexpr static T conv (const std::integral_constant&) { + return dhandy::buildtime_int_to_ary().to_string_view(); } }; } //namespace implem template - constexpr inline To int_conv (const From& from) { - return implem::IntConv::conv(from); + constexpr inline To int_conv (const From& from, bool all_caps=false) { + if (all_caps) + return implem::IntConv>::conv(from); + else + return implem::IntConv>::conv(from); } template constexpr inline To int_conv_temporary (const From& from) { - return implem::IntConv::conv(from); + return implem::IntConv>::conv(from); } } //namespace dhandy diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index ebbe445..cfe9276 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -171,3 +171,27 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { AryConversionTestHelper("-1", -1, false); AryConversionTestHelper("-510123123123", -510123123123, false); } + +TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") { + using dhandy::int_conv; + using std::string_view; + using std::integral_constant; + + constexpr auto bool1 = int_conv(integral_constant{}); + CHECK("1" == bool1); + + constexpr auto bool2 = int_conv(integral_constant{}); + CHECK("0" == bool2); + + constexpr auto int1 = int_conv(integral_constant{}); + CHECK("42" == int1); + + constexpr auto int2 = int_conv(integral_constant{}); + CHECK("7777777" == int2); + + constexpr auto int3 = int_conv(integral_constant{}); + CHECK("-1234" == int3); + + constexpr auto int4 = int_conv(integral_constant{}); + CHECK("-256" == int4); +} From 562eba5f689faf6d45a5fcf78ad42d22eecc8c50 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 02:40:19 +0200 Subject: [PATCH 26/60] Delete sequence_bt.hpp This stuff has been in the standard lib for a long time now. --- include/duckhandy/sequence_bt.hpp | 54 ------------------------------- include/duckhandy/string_bt.hpp | 12 +++---- 2 files changed, 6 insertions(+), 60 deletions(-) delete mode 100644 include/duckhandy/sequence_bt.hpp diff --git a/include/duckhandy/sequence_bt.hpp b/include/duckhandy/sequence_bt.hpp deleted file mode 100644 index ee92e92..0000000 --- a/include/duckhandy/sequence_bt.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2016-2021 Michele Santullo - * This file is part of "duckhandy". - * - * "duckhandy" 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. - * - * "duckhandy" 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 "duckhandy". If not, see . - */ - -#ifndef id4FAEF395B9ED47CB9D6B50B54C9A289A -#define id4FAEF395B9ED47CB9D6B50B54C9A289A - -#include - -namespace dhandy { - namespace bt { - template - struct number_seq { - }; - - template - using index_seq = number_seq; - - namespace implem { - template - struct range_builder; - - template - struct range_builder { - typedef number_seq type; - }; - - template - struct range_builder : public range_builder { - }; - } //namespace implem - - template - using number_range = typename implem::range_builder::type; - - template - using index_range = number_range; - } //namespace bt -} //namespace dhandy - -#endif diff --git a/include/duckhandy/string_bt.hpp b/include/duckhandy/string_bt.hpp index a7f1862..9d6cdb6 100644 --- a/include/duckhandy/string_bt.hpp +++ b/include/duckhandy/string_bt.hpp @@ -18,7 +18,7 @@ #ifndef id170B0E6C34D14EBA9B92A35977BDBFB3 #define id170B0E6C34D14EBA9B92A35977BDBFB3 -#include "sequence_bt.hpp" +#include #include #include #include @@ -58,7 +58,7 @@ namespace dhandy { private: template - constexpr string ( const index_seq&, const value_type* parString ); + constexpr string ( const std::index_sequence&, const value_type* parString ); const value_type m_data[S]; }; @@ -70,7 +70,7 @@ namespace dhandy { namespace implem { template - constexpr string concat ( const index_seq&, const string& parLeft, const string& parRight ) { + constexpr string concat ( const std::index_sequence&, const string& parLeft, const string& parRight ) { return string( (I < S - 1 ? parLeft[I] : (I < S + S2 - 2 ? parRight[I - (S - 1)] : '\0'))... ); @@ -83,14 +83,14 @@ namespace dhandy { template template - constexpr string::string (const index_seq&, const value_type* parString) : + constexpr string::string (const std::index_sequence&, const value_type* parString) : m_data{parString[I]...} { } template inline constexpr string::string (const value_type* parString) : - string(index_range<0, S>(), parString) + string(std::make_index_sequence(), parString) { } @@ -104,7 +104,7 @@ namespace dhandy { template template constexpr inline string string::operator+ (const string& parOther) const { - return implem::concat(index_range<0, S + S2 - 1>(), string(m_data), parOther); + return implem::concat(std::make_index_sequence(), string(m_data), parOther); } template From 9539b5430f6265b34f0b8e8bc5c90d1ef708caa6 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 02:41:41 +0200 Subject: [PATCH 27/60] Some small code improvements --- include/duckhandy/bitfield_pack.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/duckhandy/bitfield_pack.hpp b/include/duckhandy/bitfield_pack.hpp index a837587..bccc161 100644 --- a/include/duckhandy/bitfield_pack.hpp +++ b/include/duckhandy/bitfield_pack.hpp @@ -99,7 +99,8 @@ namespace dhandy { }; template - constexpr inline T make_mask (std::size_t len) { + [[gnu::const]] + constexpr inline T make_mask (std::size_t len) noexcept { return (1 << len) - 1; } } //namespace implem @@ -118,7 +119,7 @@ namespace dhandy { template friend U get (const BitfieldPack&); template friend void set (BitfieldPack&, V); typedef implem::BitfieldData base_type; - static_assert(Facts::LargestSize <= sizeof(T) * CHAR_BIT, "Bitfield size can't be larget than the data type itself"); + static_assert(Facts::LargestSize <= sizeof(T) * CHAR_BIT, "Bitfield size can't be larger than the data type itself"); public: BitfieldPack (T init=T{}) : base_type(init) {} }; @@ -136,14 +137,15 @@ namespace dhandy { const constexpr bool bleeds_into_next = reloffs + so.size > sizeof(T) * CHAR_BIT; const T bottom = static_cast&>(pack).value() >> reloffs; - if (bleeds_into_next) { - const std::size_t safe_index = index + 2 - not bleeds_into_next; + if constexpr (bleeds_into_next) { + const std::size_t safe_index = index + 2; const T val = static_cast&>(pack).value(); const T top = val << (sizeof(T) * CHAR_BIT - reloffs); return static_cast(top | bottom) & make_mask(so.size); } - - return bottom & make_mask(so.size); + else { + return bottom & make_mask(so.size); + } } template From d0e7ca0bee48c46c8fd883e014f4b58fb6cfba87 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 02:48:07 +0200 Subject: [PATCH 28/60] Merge functions --- include/duckhandy/implem/int_conv.hpp | 5 +++-- include/duckhandy/implem/reversed_sized_array_bt.hpp | 7 ------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 5dc8903..11cceb0 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -320,8 +320,9 @@ namespace dhandy { return std::string(int_to_ary(num).to_string_view()); } - template - std::string operator+ (std::string a, const ReversedSizedArray& b) { + template + inline + std::basic_string operator+ (std::basic_string a, const ReversedSizedArray& b) { a.append(b.data(), b.size() - 1); return a; } diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index a6904f2..36e886c 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -72,13 +72,6 @@ namespace dhandy { stream << arr.to_string_view(); return stream; } - - template - inline - std::basic_string operator+ (std::basic_string&& a, const ReversedSizedArray& b) { - a.insert(a.end(), b.begin(), b.end()); - return a; - } #endif } //namespace dhandy From 1ec0e143fd4a2c86c335782dd983900b6f7f04cc Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 02:48:49 +0200 Subject: [PATCH 29/60] Replace string with basic_string --- include/duckhandy/implem/reversed_sized_array_bt.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index 36e886c..30fcc80 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -54,8 +54,8 @@ namespace dhandy { constexpr std::basic_string_view to_string_view() const { return to>(); } bool operator== (const std::basic_string_view& other) const { return to_string_view() == other; } bool operator!= (const std::basic_string_view& other) const { return not operator==(other); } - bool operator== (const std::string& other) const { return to_string_view() == other; } - bool operator!= (const std::string& other) const { return not operator==(other); } + bool operator== (const std::basic_string& other) const { return to_string_view() == other; } + bool operator!= (const std::basic_string& other) const { return not operator==(other); } bool operator== (const T* other) const { return to_string_view() == std::basic_string_view(other); } bool operator!= (const T* other) const { return not operator==(other); } #endif From db554b8b8597c4eb3353adcaff9d3a16cbd1440b Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 28 May 2021 02:54:18 +0200 Subject: [PATCH 30/60] Update Catch2 to latest v2.x branch --- lib/Catch2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Catch2 b/lib/Catch2 index 5c88067..531a149 160000 --- a/lib/Catch2 +++ b/lib/Catch2 @@ -1 +1 @@ -Subproject commit 5c88067bd339465513af4aec606bd2292f1b594a +Subproject commit 531a149ae70dd4143ba1ac28e33d40ab612d3897 From d3731253e4e355337c6f5dd90bdd5a8ed83ca30b Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 00:34:39 +0200 Subject: [PATCH 31/60] Import build time tiger hasd from doorkeeper --- include/duckhandy/tiger_bt.hpp | 59 ++++ include/duckhandy/tiger_bt.inl | 498 +++++++++++++++++++++++++++++++++ test/unit/CMakeLists.txt | 1 + test/unit/tiger_test.cpp | 54 ++++ 4 files changed, 612 insertions(+) create mode 100644 include/duckhandy/tiger_bt.hpp create mode 100644 include/duckhandy/tiger_bt.inl create mode 100644 test/unit/tiger_test.cpp diff --git a/include/duckhandy/tiger_bt.hpp b/include/duckhandy/tiger_bt.hpp new file mode 100644 index 0000000..f3e8a0e --- /dev/null +++ b/include/duckhandy/tiger_bt.hpp @@ -0,0 +1,59 @@ +/* Copyright 2015, Michele Santullo + * This file is part of DoorKeeper. + * + * DoorKeeper 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. + * + * DoorKeeper 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 DoorKeeper. If not, see . + */ + +#ifndef id1E6CCE44307549A9B6C9E4E5923AC002 +#define id1E6CCE44307549A9B6C9E4E5923AC002 + +//#include "doorkeeper/helpers/hashing.hpp" +//#include "doorkeeper/implem/compatibility.h" +#include +#include +#include + +namespace dk { + struct HashType { + constexpr HashType ( uint64_t parA, uint64_t parB, uint64_t parC ) : + a(parA), b(parB), c(parC) + { + } + constexpr HashType ( uint64_t parAP, uint64_t parA, uint64_t parBP, uint64_t parB, uint64_t parCP, uint64_t parC ) : + a(0 == parAP ? parA : (0 == parBP ? parB : (0 == parCP ? parC : throw 0))), + b(1 == parAP ? parA : (1 == parBP ? parB : (1 == parCP ? parC : throw 0))), + c(2 == parAP ? parA : (2 == parBP ? parB : (2 == parCP ? parC : throw 0))) + { + } + constexpr HashType ( const HashType& ) = default; + constexpr uint64_t operator[] ( uint64_t parIndex ) const { + return (parIndex == 0 ? a : + (parIndex == 1 ? b : + (parIndex == 2 ? c : throw 0) + ) + ); + } + + uint64_t a; + uint64_t b; + uint64_t c; + }; + + [[gnu::const]] + constexpr HashType tiger ( const char* parStr, uint64_t parLen, char parPad ); +} //namespace dk + +#include "tiger_bt.inl" + +#endif diff --git a/include/duckhandy/tiger_bt.inl b/include/duckhandy/tiger_bt.inl new file mode 100644 index 0000000..80ad908 --- /dev/null +++ b/include/duckhandy/tiger_bt.inl @@ -0,0 +1,498 @@ +/* Copyright 2015, Michele Santullo + * This file is part of DoorKeeper. + * + * DoorKeeper 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. + * + * DoorKeeper 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 DoorKeeper. If not, see . + */ + +#ifndef lengthof +# define lengthof(a) (sizeof(a) / sizeof((a)[0])) +# define UNDEF_lengthof +#endif + +namespace dk { + namespace implem { + constexpr const uint64_t table[4*256] = {0x02AAB17CF7E90C5EULL, 0xAC424B03E243A8ECULL, + 0x72CD5BE30DD5FCD3ULL, 0x6D019B93F6F97F3AULL, 0xCD9978FFD21F9193ULL, 0x7573A1C9708029E2ULL, + 0xB164326B922A83C3ULL, 0x46883EEE04915870ULL, 0xEAACE3057103ECE6ULL, 0xC54169B808A3535CULL, + 0x4CE754918DDEC47CULL, 0x0AA2F4DFDC0DF40CULL, 0x10B76F18A74DBEFAULL, 0xC6CCB6235AD1AB6AULL, + 0x13726121572FE2FFULL, 0x1A488C6F199D921EULL, 0x4BC9F9F4DA0007CAULL, 0x26F5E6F6E85241C7ULL, + 0x859079DBEA5947B6ULL, 0x4F1885C5C99E8C92ULL, 0xD78E761EA96F864BULL, 0x8E36428C52B5C17DULL, + 0x69CF6827373063C1ULL, 0xB607C93D9BB4C56EULL, 0x7D820E760E76B5EAULL, 0x645C9CC6F07FDC42ULL, + 0xBF38A078243342E0ULL, 0x5F6B343C9D2E7D04ULL, 0xF2C28AEB600B0EC6ULL, 0x6C0ED85F7254BCACULL, + 0x71592281A4DB4FE5ULL, 0x1967FA69CE0FED9FULL, 0xFD5293F8B96545DBULL, 0xC879E9D7F2A7600BULL, + 0x860248920193194EULL, 0xA4F9533B2D9CC0B3ULL, 0x9053836C15957613ULL, 0xDB6DCF8AFC357BF1ULL, + 0x18BEEA7A7A370F57ULL, 0x037117CA50B99066ULL, 0x6AB30A9774424A35ULL, 0xF4E92F02E325249BULL, + 0x7739DB07061CCAE1ULL, 0xD8F3B49CECA42A05ULL, 0xBD56BE3F51382F73ULL, 0x45FAED5843B0BB28ULL, + 0x1C813D5C11BF1F83ULL, 0x8AF0E4B6D75FA169ULL, 0x33EE18A487AD9999ULL, 0x3C26E8EAB1C94410ULL, + 0xB510102BC0A822F9ULL, 0x141EEF310CE6123BULL, 0xFC65B90059DDB154ULL, 0xE0158640C5E0E607ULL, + 0x884E079826C3A3CFULL, 0x930D0D9523C535FDULL, 0x35638D754E9A2B00ULL, 0x4085FCCF40469DD5ULL, + 0xC4B17AD28BE23A4CULL, 0xCAB2F0FC6A3E6A2EULL, 0x2860971A6B943FCDULL, 0x3DDE6EE212E30446ULL, + 0x6222F32AE01765AEULL, 0x5D550BB5478308FEULL, 0xA9EFA98DA0EDA22AULL, 0xC351A71686C40DA7ULL, + 0x1105586D9C867C84ULL, 0xDCFFEE85FDA22853ULL, 0xCCFBD0262C5EEF76ULL, 0xBAF294CB8990D201ULL, + 0xE69464F52AFAD975ULL, 0x94B013AFDF133E14ULL, 0x06A7D1A32823C958ULL, 0x6F95FE5130F61119ULL, + 0xD92AB34E462C06C0ULL, 0xED7BDE33887C71D2ULL, 0x79746D6E6518393EULL, 0x5BA419385D713329ULL, + 0x7C1BA6B948A97564ULL, 0x31987C197BFDAC67ULL, 0xDE6C23C44B053D02ULL, 0x581C49FED002D64DULL, + 0xDD474D6338261571ULL, 0xAA4546C3E473D062ULL, 0x928FCE349455F860ULL, 0x48161BBACAAB94D9ULL, + 0x63912430770E6F68ULL, 0x6EC8A5E602C6641CULL, 0x87282515337DDD2BULL, 0x2CDA6B42034B701BULL, + 0xB03D37C181CB096DULL, 0xE108438266C71C6FULL, 0x2B3180C7EB51B255ULL, 0xDF92B82F96C08BBCULL, + 0x5C68C8C0A632F3BAULL, 0x5504CC861C3D0556ULL, 0xABBFA4E55FB26B8FULL, 0x41848B0AB3BACEB4ULL, + 0xB334A273AA445D32ULL, 0xBCA696F0A85AD881ULL, 0x24F6EC65B528D56CULL, 0x0CE1512E90F4524AULL, + 0x4E9DD79D5506D35AULL, 0x258905FAC6CE9779ULL, 0x2019295B3E109B33ULL, 0xF8A9478B73A054CCULL, + 0x2924F2F934417EB0ULL, 0x3993357D536D1BC4ULL, 0x38A81AC21DB6FF8BULL, 0x47C4FBF17D6016BFULL, + 0x1E0FAADD7667E3F5ULL, 0x7ABCFF62938BEB96ULL, 0xA78DAD948FC179C9ULL, 0x8F1F98B72911E50DULL, + 0x61E48EAE27121A91ULL, 0x4D62F7AD31859808ULL, 0xECEBA345EF5CEAEBULL, 0xF5CEB25EBC9684CEULL, + 0xF633E20CB7F76221ULL, 0xA32CDF06AB8293E4ULL, 0x985A202CA5EE2CA4ULL, 0xCF0B8447CC8A8FB1ULL, + 0x9F765244979859A3ULL, 0xA8D516B1A1240017ULL, 0x0BD7BA3EBB5DC726ULL, 0xE54BCA55B86ADB39ULL, + 0x1D7A3AFD6C478063ULL, 0x519EC608E7669EDDULL, 0x0E5715A2D149AA23ULL, 0x177D4571848FF194ULL, + 0xEEB55F3241014C22ULL, 0x0F5E5CA13A6E2EC2ULL, 0x8029927B75F5C361ULL, 0xAD139FABC3D6E436ULL, + 0x0D5DF1A94CCF402FULL, 0x3E8BD948BEA5DFC8ULL, 0xA5A0D357BD3FF77EULL, 0xA2D12E251F74F645ULL, + 0x66FD9E525E81A082ULL, 0x2E0C90CE7F687A49ULL, 0xC2E8BCBEBA973BC5ULL, 0x000001BCE509745FULL, + 0x423777BBE6DAB3D6ULL, 0xD1661C7EAEF06EB5ULL, 0xA1781F354DAACFD8ULL, 0x2D11284A2B16AFFCULL, + 0xF1FC4F67FA891D1FULL, 0x73ECC25DCB920ADAULL, 0xAE610C22C2A12651ULL, 0x96E0A810D356B78AULL, + 0x5A9A381F2FE7870FULL, 0xD5AD62EDE94E5530ULL, 0xD225E5E8368D1427ULL, 0x65977B70C7AF4631ULL, + 0x99F889B2DE39D74FULL, 0x233F30BF54E1D143ULL, 0x9A9675D3D9A63C97ULL, 0x5470554FF334F9A8ULL, + 0x166ACB744A4F5688ULL, 0x70C74CAAB2E4AEADULL, 0xF0D091646F294D12ULL, 0x57B82A89684031D1ULL, + 0xEFD95A5A61BE0B6BULL, 0x2FBD12E969F2F29AULL, 0x9BD37013FEFF9FE8ULL, 0x3F9B0404D6085A06ULL, + 0x4940C1F3166CFE15ULL, 0x09542C4DCDF3DEFBULL, 0xB4C5218385CD5CE3ULL, 0xC935B7DC4462A641ULL, + 0x3417F8A68ED3B63FULL, 0xB80959295B215B40ULL, 0xF99CDAEF3B8C8572ULL, 0x018C0614F8FCB95DULL, + 0x1B14ACCD1A3ACDF3ULL, 0x84D471F200BB732DULL, 0xC1A3110E95E8DA16ULL, 0x430A7220BF1A82B8ULL, + 0xB77E090D39DF210EULL, 0x5EF4BD9F3CD05E9DULL, 0x9D4FF6DA7E57A444ULL, 0xDA1D60E183D4A5F8ULL, + 0xB287C38417998E47ULL, 0xFE3EDC121BB31886ULL, 0xC7FE3CCC980CCBEFULL, 0xE46FB590189BFD03ULL, + 0x3732FD469A4C57DCULL, 0x7EF700A07CF1AD65ULL, 0x59C64468A31D8859ULL, 0x762FB0B4D45B61F6ULL, + 0x155BAED099047718ULL, 0x68755E4C3D50BAA6ULL, 0xE9214E7F22D8B4DFULL, 0x2ADDBF532EAC95F4ULL, + 0x32AE3909B4BD0109ULL, 0x834DF537B08E3450ULL, 0xFA209DA84220728DULL, 0x9E691D9B9EFE23F7ULL, + 0x0446D288C4AE8D7FULL, 0x7B4CC524E169785BULL, 0x21D87F0135CA1385ULL, 0xCEBB400F137B8AA5ULL, + 0x272E2B66580796BEULL, 0x3612264125C2B0DEULL, 0x057702BDAD1EFBB2ULL, 0xD4BABB8EACF84BE9ULL, + 0x91583139641BC67BULL, 0x8BDC2DE08036E024ULL, 0x603C8156F49F68EDULL, 0xF7D236F7DBEF5111ULL, + 0x9727C4598AD21E80ULL, 0xA08A0896670A5FD7ULL, 0xCB4A8F4309EBA9CBULL, 0x81AF564B0F7036A1ULL, + 0xC0B99AA778199ABDULL, 0x959F1EC83FC8E952ULL, 0x8C505077794A81B9ULL, 0x3ACAAF8F056338F0ULL, + 0x07B43F50627A6778ULL, 0x4A44AB49F5ECCC77ULL, 0x3BC3D6E4B679EE98ULL, 0x9CC0D4D1CF14108CULL, + 0x4406C00B206BC8A0ULL, 0x82A18854C8D72D89ULL, 0x67E366B35C3C432CULL, 0xB923DD61102B37F2ULL, + 0x56AB2779D884271DULL, 0xBE83E1B0FF1525AFULL, 0xFB7C65D4217E49A9ULL, 0x6BDBE0E76D48E7D4ULL, + 0x08DF828745D9179EULL, 0x22EA6A9ADD53BD34ULL, 0xE36E141C5622200AULL, 0x7F805D1B8CB750EEULL, + 0xAFE5C7A59F58E837ULL, 0xE27F996A4FB1C23CULL, 0xD3867DFB0775F0D0ULL, 0xD0E673DE6E88891AULL, + 0x123AEB9EAFB86C25ULL, 0x30F1D5D5C145B895ULL, 0xBB434A2DEE7269E7ULL, 0x78CB67ECF931FA38ULL, + 0xF33B0372323BBF9CULL, 0x52D66336FB279C74ULL, 0x505F33AC0AFB4EAAULL, 0xE8A5CD99A2CCE187ULL, + 0x534974801E2D30BBULL, 0x8D2D5711D5876D90ULL, 0x1F1A412891BC038EULL, 0xD6E2E71D82E56648ULL, + 0x74036C3A497732B7ULL, 0x89B67ED96361F5ABULL, 0xFFED95D8F1EA02A2ULL, 0xE72B3BD61464D43DULL, + 0xA6300F170BDC4820ULL, 0xEBC18760ED78A77AULL, 0xE6A6BE5A05A12138ULL, 0xB5A122A5B4F87C98ULL, + 0x563C6089140B6990ULL, 0x4C46CB2E391F5DD5ULL, 0xD932ADDBC9B79434ULL, 0x08EA70E42015AFF5ULL, + 0xD765A6673E478CF1ULL, 0xC4FB757EAB278D99ULL, 0xDF11C6862D6E0692ULL, 0xDDEB84F10D7F3B16ULL, + 0x6F2EF604A665EA04ULL, 0x4A8E0F0FF0E0DFB3ULL, 0xA5EDEEF83DBCBA51ULL, 0xFC4F0A2A0EA4371EULL, + 0xE83E1DA85CB38429ULL, 0xDC8FF882BA1B1CE2ULL, 0xCD45505E8353E80DULL, 0x18D19A00D4DB0717ULL, + 0x34A0CFEDA5F38101ULL, 0x0BE77E518887CAF2ULL, 0x1E341438B3C45136ULL, 0xE05797F49089CCF9ULL, + 0xFFD23F9DF2591D14ULL, 0x543DDA228595C5CDULL, 0x661F81FD99052A33ULL, 0x8736E641DB0F7B76ULL, + 0x15227725418E5307ULL, 0xE25F7F46162EB2FAULL, 0x48A8B2126C13D9FEULL, 0xAFDC541792E76EEAULL, + 0x03D912BFC6D1898FULL, 0x31B1AAFA1B83F51BULL, 0xF1AC2796E42AB7D9ULL, 0x40A3A7D7FCD2EBACULL, + 0x1056136D0AFBBCC5ULL, 0x7889E1DD9A6D0C85ULL, 0xD33525782A7974AAULL, 0xA7E25D09078AC09BULL, + 0xBD4138B3EAC6EDD0ULL, 0x920ABFBE71EB9E70ULL, 0xA2A5D0F54FC2625CULL, 0xC054E36B0B1290A3ULL, + 0xF6DD59FF62FE932BULL, 0x3537354511A8AC7DULL, 0xCA845E9172FADCD4ULL, 0x84F82B60329D20DCULL, + 0x79C62CE1CD672F18ULL, 0x8B09A2ADD124642CULL, 0xD0C1E96A19D9E726ULL, 0x5A786A9B4BA9500CULL, + 0x0E020336634C43F3ULL, 0xC17B474AEB66D822ULL, 0x6A731AE3EC9BAAC2ULL, 0x8226667AE0840258ULL, + 0x67D4567691CAECA5ULL, 0x1D94155C4875ADB5ULL, 0x6D00FD985B813FDFULL, 0x51286EFCB774CD06ULL, + 0x5E8834471FA744AFULL, 0xF72CA0AEE761AE2EULL, 0xBE40E4CDAEE8E09AULL, 0xE9970BBB5118F665ULL, + 0x726E4BEB33DF1964ULL, 0x703B000729199762ULL, 0x4631D816F5EF30A7ULL, 0xB880B5B51504A6BEULL, + 0x641793C37ED84B6CULL, 0x7B21ED77F6E97D96ULL, 0x776306312EF96B73ULL, 0xAE528948E86FF3F4ULL, + 0x53DBD7F286A3F8F8ULL, 0x16CADCE74CFC1063ULL, 0x005C19BDFA52C6DDULL, 0x68868F5D64D46AD3ULL, + 0x3A9D512CCF1E186AULL, 0x367E62C2385660AEULL, 0xE359E7EA77DCB1D7ULL, 0x526C0773749ABE6EULL, + 0x735AE5F9D09F734BULL, 0x493FC7CC8A558BA8ULL, 0xB0B9C1533041AB45ULL, 0x321958BA470A59BDULL, + 0x852DB00B5F46C393ULL, 0x91209B2BD336B0E5ULL, 0x6E604F7D659EF19FULL, 0xB99A8AE2782CCB24ULL, + 0xCCF52AB6C814C4C7ULL, 0x4727D9AFBE11727BULL, 0x7E950D0C0121B34DULL, 0x756F435670AD471FULL, + 0xF5ADD442615A6849ULL, 0x4E87E09980B9957AULL, 0x2ACFA1DF50AEE355ULL, 0xD898263AFD2FD556ULL, + 0xC8F4924DD80C8FD6ULL, 0xCF99CA3D754A173AULL, 0xFE477BACAF91BF3CULL, 0xED5371F6D690C12DULL, + 0x831A5C285E687094ULL, 0xC5D3C90A3708A0A4ULL, 0x0F7F903717D06580ULL, 0x19F9BB13B8FDF27FULL, + 0xB1BD6F1B4D502843ULL, 0x1C761BA38FFF4012ULL, 0x0D1530C4E2E21F3BULL, 0x8943CE69A7372C8AULL, + 0xE5184E11FEB5CE66ULL, 0x618BDB80BD736621ULL, 0x7D29BAD68B574D0BULL, 0x81BB613E25E6FE5BULL, + 0x071C9C10BC07913FULL, 0xC7BEEB7909AC2D97ULL, 0xC3E58D353BC5D757ULL, 0xEB017892F38F61E8ULL, + 0xD4EFFB9C9B1CC21AULL, 0x99727D26F494F7ABULL, 0xA3E063A2956B3E03ULL, 0x9D4A8B9A4AA09C30ULL, + 0x3F6AB7D500090FB4ULL, 0x9CC0F2A057268AC0ULL, 0x3DEE9D2DEDBF42D1ULL, 0x330F49C87960A972ULL, + 0xC6B2720287421B41ULL, 0x0AC59EC07C00369CULL, 0xEF4EAC49CB353425ULL, 0xF450244EEF0129D8ULL, + 0x8ACC46E5CAF4DEB6ULL, 0x2FFEAB63989263F7ULL, 0x8F7CB9FE5D7A4578ULL, 0x5BD8F7644E634635ULL, + 0x427A7315BF2DC900ULL, 0x17D0C4AA2125261CULL, 0x3992486C93518E50ULL, 0xB4CBFEE0A2D7D4C3ULL, + 0x7C75D6202C5DDD8DULL, 0xDBC295D8E35B6C61ULL, 0x60B369D302032B19ULL, 0xCE42685FDCE44132ULL, + 0x06F3DDB9DDF65610ULL, 0x8EA4D21DB5E148F0ULL, 0x20B0FCE62FCD496FULL, 0x2C1B912358B0EE31ULL, + 0xB28317B818F5A308ULL, 0xA89C1E189CA6D2CFULL, 0x0C6B18576AAADBC8ULL, 0xB65DEAA91299FAE3ULL, + 0xFB2B794B7F1027E7ULL, 0x04E4317F443B5BEBULL, 0x4B852D325939D0A6ULL, 0xD5AE6BEEFB207FFCULL, + 0x309682B281C7D374ULL, 0xBAE309A194C3B475ULL, 0x8CC3F97B13B49F05ULL, 0x98A9422FF8293967ULL, + 0x244B16B01076FF7CULL, 0xF8BF571C663D67EEULL, 0x1F0D6758EEE30DA1ULL, 0xC9B611D97ADEB9B7ULL, + 0xB7AFD5887B6C57A2ULL, 0x6290AE846B984FE1ULL, 0x94DF4CDEACC1A5FDULL, 0x058A5BD1C5483AFFULL, + 0x63166CC142BA3C37ULL, 0x8DB8526EB2F76F40ULL, 0xE10880036F0D6D4EULL, 0x9E0523C9971D311DULL, + 0x45EC2824CC7CD691ULL, 0x575B8359E62382C9ULL, 0xFA9E400DC4889995ULL, 0xD1823ECB45721568ULL, + 0xDAFD983B8206082FULL, 0xAA7D29082386A8CBULL, 0x269FCD4403B87588ULL, 0x1B91F5F728BDD1E0ULL, + 0xE4669F39040201F6ULL, 0x7A1D7C218CF04ADEULL, 0x65623C29D79CE5CEULL, 0x2368449096C00BB1ULL, + 0xAB9BF1879DA503BAULL, 0xBC23ECB1A458058EULL, 0x9A58DF01BB401ECCULL, 0xA070E868A85F143DULL, + 0x4FF188307DF2239EULL, 0x14D565B41A641183ULL, 0xEE13337452701602ULL, 0x950E3DCF3F285E09ULL, + 0x59930254B9C80953ULL, 0x3BF299408930DA6DULL, 0xA955943F53691387ULL, 0xA15EDECAA9CB8784ULL, + 0x29142127352BE9A0ULL, 0x76F0371FFF4E7AFBULL, 0x0239F450274F2228ULL, 0xBB073AF01D5E868BULL, + 0xBFC80571C10E96C1ULL, 0xD267088568222E23ULL, 0x9671A3D48E80B5B0ULL, 0x55B5D38AE193BB81ULL, + 0x693AE2D0A18B04B8ULL, 0x5C48B4ECADD5335FULL, 0xFD743B194916A1CAULL, 0x2577018134BE98C4ULL, + 0xE77987E83C54A4ADULL, 0x28E11014DA33E1B9ULL, 0x270CC59E226AA213ULL, 0x71495F756D1A5F60ULL, + 0x9BE853FB60AFEF77ULL, 0xADC786A7F7443DBFULL, 0x0904456173B29A82ULL, 0x58BC7A66C232BD5EULL, + 0xF306558C673AC8B2ULL, 0x41F639C6B6C9772AULL, 0x216DEFE99FDA35DAULL, 0x11640CC71C7BE615ULL, + 0x93C43694565C5527ULL, 0xEA038E6246777839ULL, 0xF9ABF3CE5A3E2469ULL, 0x741E768D0FD312D2ULL, + 0x0144B883CED652C6ULL, 0xC20B5A5BA33F8552ULL, 0x1AE69633C3435A9DULL, 0x97A28CA4088CFDECULL, + 0x8824A43C1E96F420ULL, 0x37612FA66EEEA746ULL, 0x6B4CB165F9CF0E5AULL, 0x43AA1C06A0ABFB4AULL, + 0x7F4DC26FF162796BULL, 0x6CBACC8E54ED9B0FULL, 0xA6B7FFEFD2BB253EULL, 0x2E25BC95B0A29D4FULL, + 0x86D6A58BDEF1388CULL, 0xDED74AC576B6F054ULL, 0x8030BDBC2B45805DULL, 0x3C81AF70E94D9289ULL, + 0x3EFF6DDA9E3100DBULL, 0xB38DC39FDFCC8847ULL, 0x123885528D17B87EULL, 0xF2DA0ED240B1B642ULL, + 0x44CEFADCD54BF9A9ULL, 0x1312200E433C7EE6ULL, 0x9FFCC84F3A78C748ULL, 0xF0CD1F72248576BBULL, + 0xEC6974053638CFE4ULL, 0x2BA7B67C0CEC4E4CULL, 0xAC2F4DF3E5CE32EDULL, 0xCB33D14326EA4C11ULL, + 0xA4E9044CC77E58BCULL, 0x5F513293D934FCEFULL, 0x5DC9645506E55444ULL, 0x50DE418F317DE40AULL, + 0x388CB31A69DDE259ULL, 0x2DB4A83455820A86ULL, 0x9010A91E84711AE9ULL, 0x4DF7F0B7B1498371ULL, + 0xD62A2EABC0977179ULL, 0x22FAC097AA8D5C0EULL, 0xF49FCC2FF1DAF39BULL, 0x487FD5C66FF29281ULL, + 0xE8A30667FCDCA83FULL, 0x2C9B4BE3D2FCCE63ULL, 0xDA3FF74B93FBBBC2ULL, 0x2FA165D2FE70BA66ULL, + 0xA103E279970E93D4ULL, 0xBECDEC77B0E45E71ULL, 0xCFB41E723985E497ULL, 0xB70AAA025EF75017ULL, + 0xD42309F03840B8E0ULL, 0x8EFC1AD035898579ULL, 0x96C6920BE2B2ABC5ULL, 0x66AF4163375A9172ULL, + 0x2174ABDCCA7127FBULL, 0xB33CCEA64A72FF41ULL, 0xF04A4933083066A5ULL, 0x8D970ACDD7289AF5ULL, + 0x8F96E8E031C8C25EULL, 0xF3FEC02276875D47ULL, 0xEC7BF310056190DDULL, 0xF5ADB0AEBB0F1491ULL, + 0x9B50F8850FD58892ULL, 0x4975488358B74DE8ULL, 0xA3354FF691531C61ULL, 0x0702BBE481D2C6EEULL, + 0x89FB24057DEDED98ULL, 0xAC3075138596E902ULL, 0x1D2D3580172772EDULL, 0xEB738FC28E6BC30DULL, + 0x5854EF8F63044326ULL, 0x9E5C52325ADD3BBEULL, 0x90AA53CF325C4623ULL, 0xC1D24D51349DD067ULL, + 0x2051CFEEA69EA624ULL, 0x13220F0A862E7E4FULL, 0xCE39399404E04864ULL, 0xD9C42CA47086FCB7ULL, + 0x685AD2238A03E7CCULL, 0x066484B2AB2FF1DBULL, 0xFE9D5D70EFBF79ECULL, 0x5B13B9DD9C481854ULL, + 0x15F0D475ED1509ADULL, 0x0BEBCD060EC79851ULL, 0xD58C6791183AB7F8ULL, 0xD1187C5052F3EEE4ULL, + 0xC95D1192E54E82FFULL, 0x86EEA14CB9AC6CA2ULL, 0x3485BEB153677D5DULL, 0xDD191D781F8C492AULL, + 0xF60866BAA784EBF9ULL, 0x518F643BA2D08C74ULL, 0x8852E956E1087C22ULL, 0xA768CB8DC410AE8DULL, + 0x38047726BFEC8E1AULL, 0xA67738B4CD3B45AAULL, 0xAD16691CEC0DDE19ULL, 0xC6D4319380462E07ULL, + 0xC5A5876D0BA61938ULL, 0x16B9FA1FA58FD840ULL, 0x188AB1173CA74F18ULL, 0xABDA2F98C99C021FULL, + 0x3E0580AB134AE816ULL, 0x5F3B05B773645ABBULL, 0x2501A2BE5575F2F6ULL, 0x1B2F74004E7E8BA9ULL, + 0x1CD7580371E8D953ULL, 0x7F6ED89562764E30ULL, 0xB15926FF596F003DULL, 0x9F65293DA8C5D6B9ULL, + 0x6ECEF04DD690F84CULL, 0x4782275FFF33AF88ULL, 0xE41433083F820801ULL, 0xFD0DFE409A1AF9B5ULL, + 0x4325A3342CDB396BULL, 0x8AE77E62B301B252ULL, 0xC36F9E9F6655615AULL, 0x85455A2D92D32C09ULL, + 0xF2C7DEA949477485ULL, 0x63CFB4C133A39EBAULL, 0x83B040CC6EBC5462ULL, 0x3B9454C8FDB326B0ULL, + 0x56F56A9E87FFD78CULL, 0x2DC2940D99F42BC6ULL, 0x98F7DF096B096E2DULL, 0x19A6E01E3AD852BFULL, + 0x42A99CCBDBD4B40BULL, 0xA59998AF45E9C559ULL, 0x366295E807D93186ULL, 0x6B48181BFAA1F773ULL, + 0x1FEC57E2157A0A1DULL, 0x4667446AF6201AD5ULL, 0xE615EBCACFB0F075ULL, 0xB8F31F4F68290778ULL, + 0x22713ED6CE22D11EULL, 0x3057C1A72EC3C93BULL, 0xCB46ACC37C3F1F2FULL, 0xDBB893FD02AAF50EULL, + 0x331FD92E600B9FCFULL, 0xA498F96148EA3AD6ULL, 0xA8D8426E8B6A83EAULL, 0xA089B274B7735CDCULL, + 0x87F6B3731E524A11ULL, 0x118808E5CBC96749ULL, 0x9906E4C7B19BD394ULL, 0xAFED7F7E9B24A20CULL, + 0x6509EADEEB3644A7ULL, 0x6C1EF1D3E8EF0EDEULL, 0xB9C97D43E9798FB4ULL, 0xA2F2D784740C28A3ULL, + 0x7B8496476197566FULL, 0x7A5BE3E6B65F069DULL, 0xF96330ED78BE6F10ULL, 0xEEE60DE77A076A15ULL, + 0x2B4BEE4AA08B9BD0ULL, 0x6A56A63EC7B8894EULL, 0x02121359BA34FEF4ULL, 0x4CBF99F8283703FCULL, + 0x398071350CAF30C8ULL, 0xD0A77A89F017687AULL, 0xF1C1A9EB9E423569ULL, 0x8C7976282DEE8199ULL, + 0x5D1737A5DD1F7ABDULL, 0x4F53433C09A9FA80ULL, 0xFA8B0C53DF7CA1D9ULL, 0x3FD9DCBC886CCB77ULL, + 0xC040917CA91B4720ULL, 0x7DD00142F9D1DCDFULL, 0x8476FC1D4F387B58ULL, 0x23F8E7C5F3316503ULL, + 0x032A2244E7E37339ULL, 0x5C87A5D750F5A74BULL, 0x082B4CC43698992EULL, 0xDF917BECB858F63CULL, + 0x3270B8FC5BF86DDAULL, 0x10AE72BB29B5DD76ULL, 0x576AC94E7700362BULL, 0x1AD112DAC61EFB8FULL, + 0x691BC30EC5FAA427ULL, 0xFF246311CC327143ULL, 0x3142368E30E53206ULL, 0x71380E31E02CA396ULL, + 0x958D5C960AAD76F1ULL, 0xF8D6F430C16DA536ULL, 0xC8FFD13F1BE7E1D2ULL, 0x7578AE66004DDBE1ULL, + 0x05833F01067BE646ULL, 0xBB34B5AD3BFE586DULL, 0x095F34C9A12B97F0ULL, 0x247AB64525D60CA8ULL, + 0xDCDBC6F3017477D1ULL, 0x4A2E14D4DECAD24DULL, 0xBDB5E6D9BE0A1EEBULL, 0x2A7E70F7794301ABULL, + 0xDEF42D8A270540FDULL, 0x01078EC0A34C22C1ULL, 0xE5DE511AF4C16387ULL, 0x7EBB3A52BD9A330AULL, + 0x77697857AA7D6435ULL, 0x004E831603AE4C32ULL, 0xE7A21020AD78E312ULL, 0x9D41A70C6AB420F2ULL, + 0x28E06C18EA1141E6ULL, 0xD2B28CBD984F6B28ULL, 0x26B75F6C446E9D83ULL, 0xBA47568C4D418D7FULL, + 0xD80BADBFE6183D8EULL, 0x0E206D7F5F166044ULL, 0xE258A43911CBCA3EULL, 0x723A1746B21DC0BCULL, + 0xC7CAA854F5D7CDD3ULL, 0x7CAC32883D261D9CULL, 0x7690C26423BA942CULL, 0x17E55524478042B8ULL, + 0xE0BE477656A2389FULL, 0x4D289B5E67AB2DA0ULL, 0x44862B9C8FBBFD31ULL, 0xB47CC8049D141365ULL, + 0x822C1B362B91C793ULL, 0x4EB14655FB13DFD8ULL, 0x1ECBBA0714E2A97BULL, 0x6143459D5CDE5F14ULL, + 0x53A8FBF1D5F0AC89ULL, 0x97EA04D81C5E5B00ULL, 0x622181A8D4FDB3F3ULL, 0xE9BCD341572A1208ULL, + 0x1411258643CCE58AULL, 0x9144C5FEA4C6E0A4ULL, 0x0D33D06565CF620FULL, 0x54A48D489F219CA1ULL, + 0xC43E5EAC6D63C821ULL, 0xA9728B3A72770DAFULL, 0xD7934E7B20DF87EFULL, 0xE35503B61A3E86E5ULL, + 0xCAE321FBC819D504ULL, 0x129A50B3AC60BFA6ULL, 0xCD5E68EA7E9FB6C3ULL, 0xB01C90199483B1C7ULL, + 0x3DE93CD5C295376CULL, 0xAED52EDF2AB9AD13ULL, 0x2E60F512C0A07884ULL, 0xBC3D86A3E36210C9ULL, + 0x35269D9B163951CEULL, 0x0C7D6E2AD0CDB5FAULL, 0x59E86297D87F5733ULL, 0x298EF221898DB0E7ULL, + 0x55000029D1A5AA7EULL, 0x8BC08AE1B5061B45ULL, 0xC2C31C2B6C92703AULL, 0x94CC596BAF25EF42ULL, + 0x0A1D73DB22540456ULL, 0x04B6A0F9D9C4179AULL, 0xEFFDAFA2AE3D3C60ULL, 0xF7C8075BB49496C4ULL, + 0x9CC5C7141D1CD4E3ULL, 0x78BD1638218E5534ULL, 0xB2F11568F850246AULL, 0xEDFABCFA9502BC29ULL, + 0x796CE5F2DA23051BULL, 0xAAE128B0DC93537CULL, 0x3A493DA0EE4B29AEULL, 0xB5DF6B2C416895D7ULL, + 0xFCABBD25122D7F37ULL, 0x70810B58105DC4B1ULL, 0xE10FDD37F7882A90ULL, 0x524DCAB5518A3F5CULL, + 0x3C9E85878451255BULL, 0x4029828119BD34E2ULL, 0x74A05B6F5D3CECCBULL, 0xB610021542E13ECAULL, + 0x0FF979D12F59E2ACULL, 0x6037DA27E4F9CC50ULL, 0x5E92975A0DF1847DULL, 0xD66DE190D3E623FEULL, + 0x5032D6B87B568048ULL, 0x9A36B7CE8235216EULL, 0x80272A7A24F64B4AULL, 0x93EFED8B8C6916F7ULL, + 0x37DDBFF44CCE1555ULL, 0x4B95DB5D4B99BD25ULL, 0x92D3FDA169812FC0ULL, 0xFB1A4A9A90660BB6ULL, + 0x730C196946A4B9B2ULL, 0x81E289AA7F49DA68ULL, 0x64669A0F83B1A05FULL, 0x27B3FF7D9644F48BULL, + 0xCC6B615C8DB675B3ULL, 0x674F20B9BCEBBE95ULL, 0x6F31238275655982ULL, 0x5AE488713E45CF05ULL, + 0xBF619F9954C21157ULL, 0xEABAC46040A8EAE9ULL, 0x454C6FE9F2C0C1CDULL, 0x419CF6496412691CULL, + 0xD3DC3BEF265B0F70ULL, 0x6D0E60F5C3578A9EULL, 0x5B0E608526323C55ULL, 0x1A46C1A9FA1B59F5ULL, + 0xA9E245A17C4C8FFAULL, 0x65CA5159DB2955D7ULL, 0x05DB0A76CE35AFC2ULL, 0x81EAC77EA9113D45ULL, + 0x528EF88AB6AC0A0DULL, 0xA09EA253597BE3FFULL, 0x430DDFB3AC48CD56ULL, 0xC4B3A67AF45CE46FULL, + 0x4ECECFD8FBE2D05EULL, 0x3EF56F10B39935F0ULL, 0x0B22D6829CD619C6ULL, 0x17FD460A74DF2069ULL, + 0x6CF8CC8E8510ED40ULL, 0xD6C824BF3A6ECAA7ULL, 0x61243D581A817049ULL, 0x048BACB6BBC163A2ULL, + 0xD9A38AC27D44CC32ULL, 0x7FDDFF5BAAF410ABULL, 0xAD6D495AA804824BULL, 0xE1A6A74F2D8C9F94ULL, + 0xD4F7851235DEE8E3ULL, 0xFD4B7F886540D893ULL, 0x247C20042AA4BFDAULL, 0x096EA1C517D1327CULL, + 0xD56966B4361A6685ULL, 0x277DA5C31221057DULL, 0x94D59893A43ACFF7ULL, 0x64F0C51CCDC02281ULL, + 0x3D33BCC4FF6189DBULL, 0xE005CB184CE66AF1ULL, 0xFF5CCD1D1DB99BEAULL, 0xB0B854A7FE42980FULL, + 0x7BD46A6A718D4B9FULL, 0xD10FA8CC22A5FD8CULL, 0xD31484952BE4BD31ULL, 0xC7FA975FCB243847ULL, + 0x4886ED1E5846C407ULL, 0x28CDDB791EB70B04ULL, 0xC2B00BE2F573417FULL, 0x5C9590452180F877ULL, + 0x7A6BDDFFF370EB00ULL, 0xCE509E38D6D9D6A4ULL, 0xEBEB0F00647FA702ULL, 0x1DCC06CF76606F06ULL, + 0xE4D9F28BA286FF0AULL, 0xD85A305DC918C262ULL, 0x475B1D8732225F54ULL, 0x2D4FB51668CCB5FEULL, + 0xA679B9D9D72BBA20ULL, 0x53841C0D912D43A5ULL, 0x3B7EAA48BF12A4E8ULL, 0x781E0E47F22F1DDFULL, + 0xEFF20CE60AB50973ULL, 0x20D261D19DFFB742ULL, 0x16A12B03062A2E39ULL, 0x1960EB2239650495ULL, + 0x251C16FED50EB8B8ULL, 0x9AC0C330F826016EULL, 0xED152665953E7671ULL, 0x02D63194A6369570ULL, + 0x5074F08394B1C987ULL, 0x70BA598C90B25CE1ULL, 0x794A15810B9742F6ULL, 0x0D5925E9FCAF8C6CULL, + 0x3067716CD868744EULL, 0x910AB077E8D7731BULL, 0x6A61BBDB5AC42F61ULL, 0x93513EFBF0851567ULL, + 0xF494724B9E83E9D5ULL, 0xE887E1985C09648DULL, 0x34B1D3C675370CFDULL, 0xDC35E433BC0D255DULL, + 0xD0AAB84234131BE0ULL, 0x08042A50B48B7EAFULL, 0x9997C4EE44A3AB35ULL, 0x829A7B49201799D0ULL, + 0x263B8307B7C54441ULL, 0x752F95F4FD6A6CA6ULL, 0x927217402C08C6E5ULL, 0x2A8AB754A795D9EEULL, + 0xA442F7552F72943DULL, 0x2C31334E19781208ULL, 0x4FA98D7CEAEE6291ULL, 0x55C3862F665DB309ULL, + 0xBD0610175D53B1F3ULL, 0x46FE6CB840413F27ULL, 0x3FE03792DF0CFA59ULL, 0xCFE700372EB85E8FULL, + 0xA7BE29E7ADBCE118ULL, 0xE544EE5CDE8431DDULL, 0x8A781B1B41F1873EULL, 0xA5C94C78A0D2F0E7ULL, + 0x39412E2877B60728ULL, 0xA1265EF3AFC9A62CULL, 0xBCC2770C6A2506C5ULL, 0x3AB66DD5DCE1CE12ULL, + 0xE65499D04A675B37ULL, 0x7D8F523481BFD216ULL, 0x0F6F64FCEC15F389ULL, 0x74EFBE618B5B13C8ULL, + 0xACDC82B714273E1DULL, 0xDD40BFE003199D17ULL, 0x37E99257E7E061F8ULL, 0xFA52626904775AAAULL, + 0x8BBBF63A463D56F9ULL, 0xF0013F1543A26E64ULL, 0xA8307E9F879EC898ULL, 0xCC4C27A4150177CCULL, + 0x1B432F2CCA1D3348ULL, 0xDE1D1F8F9F6FA013ULL, 0x606602A047A7DDD6ULL, 0xD237AB64CC1CB2C7ULL, + 0x9B938E7225FCD1D3ULL, 0xEC4E03708E0FF476ULL, 0xFEB2FBDA3D03C12DULL, 0xAE0BCED2EE43889AULL, + 0x22CB8923EBFB4F43ULL, 0x69360D013CF7396DULL, 0x855E3602D2D4E022ULL, 0x073805BAD01F784CULL, + 0x33E17A133852F546ULL, 0xDF4874058AC7B638ULL, 0xBA92B29C678AA14AULL, 0x0CE89FC76CFAADCDULL, + 0x5F9D4E0908339E34ULL, 0xF1AFE9291F5923B9ULL, 0x6E3480F60F4A265FULL, 0xEEBF3A2AB29B841CULL, + 0xE21938A88F91B4ADULL, 0x57DFEFF845C6D3C3ULL, 0x2F006B0BF62CAAF2ULL, 0x62F479EF6F75EE78ULL, + 0x11A55AD41C8916A9ULL, 0xF229D29084FED453ULL, 0x42F1C27B16B000E6ULL, 0x2B1F76749823C074ULL, + 0x4B76ECA3C2745360ULL, 0x8C98F463B91691BDULL, 0x14BCC93CF1ADE66AULL, 0x8885213E6D458397ULL, + 0x8E177DF0274D4711ULL, 0xB49B73B5503F2951ULL, 0x10168168C3F96B6BULL, 0x0E3D963B63CAB0AEULL, + 0x8DFC4B5655A1DB14ULL, 0xF789F1356E14DE5CULL, 0x683E68AF4E51DAC1ULL, 0xC9A84F9D8D4B0FD9ULL, + 0x3691E03F52A0F9D1ULL, 0x5ED86E46E1878E80ULL, 0x3C711A0E99D07150ULL, 0x5A0865B20C4E9310ULL, + 0x56FBFC1FE4F0682EULL, 0xEA8D5DE3105EDF9BULL, 0x71ABFDB12379187AULL, 0x2EB99DE1BEE77B9CULL, + 0x21ECC0EA33CF4523ULL, 0x59A4D7521805C7A1ULL, 0x3896F5EB56AE7C72ULL, 0xAA638F3DB18F75DCULL, + 0x9F39358DABE9808EULL, 0xB7DEFA91C00B72ACULL, 0x6B5541FD62492D92ULL, 0x6DC6DEE8F92E4D5BULL, + 0x353F57ABC4BEEA7EULL, 0x735769D6DA5690CEULL, 0x0A234AA642391484ULL, 0xF6F9508028F80D9DULL, + 0xB8E319A27AB3F215ULL, 0x31AD9C1151341A4DULL, 0x773C22A57BEF5805ULL, 0x45C7561A07968633ULL, + 0xF913DA9E249DBE36ULL, 0xDA652D9B78A64C68ULL, 0x4C27A97F3BC334EFULL, 0x76621220E66B17F4ULL, + 0x967743899ACD7D0BULL, 0xF3EE5BCAE0ED6782ULL, 0x409F753600C879FCULL, 0x06D09A39B5926DB6ULL, + 0x6F83AEB0317AC588ULL, 0x01E6CA4A86381F21ULL, 0x66FF3462D19F3025ULL, 0x72207C24DDFD3BFBULL, + 0x4AF6B6D3E2ECE2EBULL, 0x9C994DBEC7EA08DEULL, 0x49ACE597B09A8BC4ULL, 0xB38C4766CF0797BAULL, + 0x131B9373C57C2A75ULL, 0xB1822CCE61931E58ULL, 0x9D7555B909BA1C0CULL, 0x127FAFDD937D11D2ULL, + 0x29DA3BADC66D92E4ULL, 0xA2C1D57154C2ECBCULL, 0x58C5134D82F6FE24ULL, 0x1C3AE3515B62274FULL, + 0xE907C82E01CB8126ULL, 0xF8ED091913E37FCBULL, 0x3249D8F9C80046C9ULL, 0x80CF9BEDE388FB63ULL, + 0x1881539A116CF19EULL, 0x5103F3F76BD52457ULL, 0x15B7E6F5AE47F7A8ULL, 0xDBD7C6DED47E9CCFULL, + 0x44E55C410228BB1AULL, 0xB647D4255EDB4E99ULL, 0x5D11882BB8AAFC30ULL, 0xF5098BBB29D3212AULL, + 0x8FB5EA14E90296B3ULL, 0x677B942157DD025AULL, 0xFB58E7C0A390ACB5ULL, 0x89D3674C83BD4A01ULL, + 0x9E2DA4DF4BF3B93BULL, 0xFCC41E328CAB4829ULL, 0x03F38C96BA582C52ULL, 0xCAD1BDBD7FD85DB2ULL, + 0xBBB442C16082AE83ULL, 0xB95FE86BA5DA9AB0ULL, 0xB22E04673771A93FULL, 0x845358C9493152D8ULL, + 0xBE2A488697B4541EULL, 0x95A2DC2DD38E6966ULL, 0xC02C11AC923C852BULL, 0x2388B1990DF2A87BULL, + 0x7C8008FA1B4F37BEULL, 0x1F70D0C84D54E503ULL, 0x5490ADEC7ECE57D4ULL, 0x002B3C27D9063A3AULL, + 0x7EAEA3848030A2BFULL, 0xC602326DED2003C0ULL, 0x83A7287D69A94086ULL, 0xC57A5FCB30F57A8AULL, + 0xB56844E479EBE779ULL, 0xA373B40F05DCBCE9ULL, 0xD71A786E88570EE2ULL, 0x879CBACDBDE8F6A0ULL, + 0x976AD1BCC164A32FULL, 0xAB21E25E9666D78BULL, 0x901063AAE5E5C33CULL, 0x9818B34448698D90ULL, + 0xE36487AE3E1E8ABBULL, 0xAFBDF931893BDCB4ULL, 0x6345A0DC5FBBD519ULL, 0x8628FE269B9465CAULL, + 0x1E5D01603F9C51ECULL, 0x4DE44006A15049B7ULL, 0xBF6C70E5F776CBB1ULL, 0x411218F2EF552BEDULL, + 0xCB0C0708705A36A3ULL, 0xE74D14754F986044ULL, 0xCD56D9430EA8280EULL, 0xC12591D7535F5065ULL, + 0xC83223F1720AEF96ULL, 0xC3A0396F7363A51FULL }; + + constexpr uint64_t buff_to_uint64_with_filling (const char* parStr, const uint64_t parAvailLen) { + return ( + parAvailLen == 0 ? + 0 + : + //static_cast(static_cast(parStr[0])) << + // (CHAR_BIT * (parAvailLen - 1)) bitor buff_to_uint64_with_filling(parStr + 1, parAvailLen - 1) + static_cast(static_cast(parStr[0])) bitor (buff_to_uint64_with_filling(parStr + 1, parAvailLen - 1) << CHAR_BIT) + ); + } + + constexpr uint64_t buff_to_uint64_fill_ifn (const char* parStr, uint64_t parIndex, uint64_t parBuffLen, char parPad) { + return (sizeof(uint64_t) * parIndex >= parBuffLen ? + (sizeof(uint64_t) * parIndex == parBuffLen ? + static_cast(static_cast(parPad)) + : + 0 + ) + : + (sizeof(uint64_t) * parIndex + sizeof(uint64_t) <= parBuffLen ? + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * parIndex, sizeof(uint64_t)) + : + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * parIndex, parBuffLen % sizeof(uint64_t)) bitor + static_cast(static_cast(parPad)) << ((parBuffLen % sizeof(uint64_t)) * CHAR_BIT) + ) + ); + } + + struct TigerBlock { + constexpr explicit TigerBlock ( const char* parStr ) : + data{ + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 0, sizeof(uint64_t)), + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 1, sizeof(uint64_t)), + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 2, sizeof(uint64_t)), + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 3, sizeof(uint64_t)), + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 4, sizeof(uint64_t)), + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 5, sizeof(uint64_t)), + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 6, sizeof(uint64_t)), + buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 7, sizeof(uint64_t)) + } + { + } + constexpr TigerBlock ( const TigerBlock& ) = default; + constexpr TigerBlock ( uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g, uint64_t h) : + data{a, b, c, d, e, f, g, h} + { + } + constexpr TigerBlock ( const char* parStr, uint64_t parLen, char parPad ) : + data{ + buff_to_uint64_fill_ifn(parStr, 0, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 1, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 2, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 3, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 4, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 5, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 6, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 7, parLen, parPad) + } + { + } + constexpr TigerBlock ( const char* parStr, uint64_t parLen, char parPad, uint64_t parData7 ) : + data{ + buff_to_uint64_fill_ifn(parStr, 0, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 1, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 2, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 3, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 4, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 5, parLen, parPad), + buff_to_uint64_fill_ifn(parStr, 6, parLen, parPad), + (parLen + 1 <= sizeof(uint64_t) * 7 ? parData7 : throw 0) + } + { + } + + constexpr uint64_t operator[] (std::size_t parIndex) const { return (parIndex < lengthof(data) ? data[parIndex] : throw 0); } + + const uint64_t data[8]; + }; + + constexpr uint64_t gb (uint64_t r, uint64_t a) { + return (r >> (a * CHAR_BIT)) bitand 0xff; + } + + constexpr HashType round (uint64_t mul, uint64_t a, uint64_t b, uint64_t c, uint64_t x, const TigerBlock& block, const HashType& hash) { + return HashType( + a, + hash[a] - ( + table[ gb(hash[c] xor block[x], 0)] xor + table[256 + gb(hash[c] xor block[x], 2)] xor + table[512 + gb(hash[c] xor block[x], 4)] xor + table[768 + gb(hash[c] xor block[x], 6)]), + b, + (hash[b] + ( + table[768 + gb(hash[c] xor block[x], 1)] xor + table[512 + gb(hash[c] xor block[x], 3)] xor + table[256 + gb(hash[c] xor block[x], 5)] xor + table[ gb(hash[c] xor block[x], 7)])) * mul, + c, + hash[c] xor block[x] + ); + } + + constexpr HashType pass (uint64_t a, uint64_t b, uint64_t c, uint64_t mul, const TigerBlock& block, const HashType& hash, uint64_t x=0) { + return ( + 8 == x ? + //if 0 == x + hash + : //else + pass( + b, + c, + a, + mul, + block, + round(mul, a, b, c, x, block, hash), + x + 1 + ) + ); + } + + template constexpr uint64_t key_sched_op (const TigerBlock& i); + template<> constexpr uint64_t key_sched_op<0,1> (const TigerBlock& i) { return i[0] - (i[7] ^ 0xA5A5A5A5A5A5A5A5ULL); } + template<> constexpr uint64_t key_sched_op<1,1> (const TigerBlock& i) { return i[1] ^ key_sched_op<0,1>(i); } + template<> constexpr uint64_t key_sched_op<2,1> (const TigerBlock& i) { return i[2] + key_sched_op<1,1>(i); } + template<> constexpr uint64_t key_sched_op<3,1> (const TigerBlock& i) { return i[3] - (key_sched_op<2,1>(i) ^ ((~key_sched_op<1,1>(i)) << 19)); } + template<> constexpr uint64_t key_sched_op<4,1> (const TigerBlock& i) { return i[4] ^ key_sched_op<3,1>(i); } + template<> constexpr uint64_t key_sched_op<5,1> (const TigerBlock& i) { return i[5] + key_sched_op<4,1>(i); } + template<> constexpr uint64_t key_sched_op<6,1> (const TigerBlock& i) { return i[6] - (key_sched_op<5,1>(i) ^ ((~key_sched_op<4,1>(i)) >> 23)); } + template<> constexpr uint64_t key_sched_op<7,1> (const TigerBlock& i) { return i[7] ^ key_sched_op<6,1>(i); } + template<> constexpr uint64_t key_sched_op<0,2> (const TigerBlock& i) { return key_sched_op<0,1>(i) + key_sched_op<7,1>(i); } + template<> constexpr uint64_t key_sched_op<1,2> (const TigerBlock& i) { return key_sched_op<1,1>(i) - (key_sched_op<0,2>(i) ^ ((~key_sched_op<7,1>(i)) << 19)); } + template<> constexpr uint64_t key_sched_op<2,2> (const TigerBlock& i) { return key_sched_op<2,1>(i) ^ key_sched_op<1,2>(i); } + template<> constexpr uint64_t key_sched_op<3,2> (const TigerBlock& i) { return key_sched_op<3,1>(i) + key_sched_op<2,2>(i); } + template<> constexpr uint64_t key_sched_op<4,2> (const TigerBlock& i) { return key_sched_op<4,1>(i) - (key_sched_op<3,2>(i) ^ ((~key_sched_op<2,2>(i)) >> 23)); } + template<> constexpr uint64_t key_sched_op<5,2> (const TigerBlock& i) { return key_sched_op<5,1>(i) ^ key_sched_op<4,2>(i); } + template<> constexpr uint64_t key_sched_op<6,2> (const TigerBlock& i) { return key_sched_op<6,1>(i) + key_sched_op<5,2>(i); } + template<> constexpr uint64_t key_sched_op<7,2> (const TigerBlock& i) { return key_sched_op<7,1>(i) - (key_sched_op<6,2>(i) ^ 0x0123456789ABCDEFULL); } + + constexpr TigerBlock key_sched (const TigerBlock& parBlock) { + return TigerBlock( + key_sched_op<0,2>(parBlock), + key_sched_op<1,2>(parBlock), + key_sched_op<2,2>(parBlock), + key_sched_op<3,2>(parBlock), + key_sched_op<4,2>(parBlock), + key_sched_op<5,2>(parBlock), + key_sched_op<6,2>(parBlock), + key_sched_op<7,2>(parBlock) + ); + } + + constexpr HashType finalize_tiger_step (HashType parOriginal, HashType parPartial) { + return HashType( + parPartial.a ^ parOriginal.a, + parPartial.b - parOriginal.b, + parPartial.c + parOriginal.c + ); + } + + constexpr HashType tiger_block (const TigerBlock& parBlock, HashType parHash) { + return finalize_tiger_step( + parHash, + pass(1, 2, 0, 9, key_sched(key_sched(parBlock)), + pass(2, 0, 1, 7, key_sched(parBlock), + pass(0, 1, 2, 5, parBlock, parHash) + ) + ) + ); + } + + constexpr HashType tiger_block (const char* parStr, HashType parHash) { + return tiger_block(TigerBlock(parStr), parHash); + } + + constexpr HashType tiger_chunk (const char* parStr, uint64_t parLen, HashType parHash) { + return (parLen == 0 ? + //if parLen == 0 + parHash + : + //else + tiger_chunk(parStr + 64, parLen - 64, tiger_block(parStr, parHash)) + ); + } + + constexpr HashType tiger_last_chunk (const char* parStr, uint64_t parLen, uint64_t parRealLen, HashType parHash, char parPad) { + return ( + parLen + 1 + ((8 - parLen - 1) bitand 7) == 64 ? + tiger_block( + TigerBlock(0, 0, 0, 0, 0, 0, 0, parRealLen << uint64_t(3)), + tiger_block(TigerBlock(parStr, parLen, parPad), parHash) + ) + : + tiger_block(TigerBlock(parStr, parLen, parPad, parRealLen << uint64_t(3)), parHash) + ); + } + } //namespace implem + + constexpr HashType tiger (const char* parStr, uint64_t parLen, char parPad) { + return implem::tiger_last_chunk( + parStr + (parLen bitand ~static_cast(0x3f)), + parLen - (parLen bitand ~static_cast(0x3f)), + parLen, + implem::tiger_chunk( + parStr, + parLen bitand ~static_cast(0x3f), + HashType(0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL) + ), + parPad + ); + } +} //namespace dk + +#if defined UNDEF_lengthof +# undef lengthof +# undef UNDEF_lengthof +#endif diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 16efbcf..049d6da 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -8,6 +8,7 @@ add_executable(${PROJECT_NAME} bitfield_pack_test.cpp resource_pool_test.cpp version_test.cpp + tiger_test.cpp ) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/test/unit/tiger_test.cpp b/test/unit/tiger_test.cpp new file mode 100644 index 0000000..9af7d89 --- /dev/null +++ b/test/unit/tiger_test.cpp @@ -0,0 +1,54 @@ +/* Copyright 2016-2021 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#include "catch2/catch.hpp" +#include "duckhandy/tiger_bt.hpp" + +TEST_CASE("Build-time Tiger hash tests", "[hash][bt][tiger]") { + using dk::tiger; + using dk::HashType; + + constexpr HashType h1 = tiger("", 0, 0x80); //v2 + CHECK(h1.a == 0x738701f675be4144); + CHECK(h1.b == 0x924b374527c206c2); + CHECK(h1.c == 0x419f91ef3f31a84a); + + constexpr HashType h2 = tiger("", 0, 0x01); //v1 + CHECK(h2.a == 0x24f0130c63ac9332); + CHECK(h2.b == 0x16166e76b1bb925f); + CHECK(h2.c == 0xf373de2d49584e7a); + + constexpr HashType h3 = tiger("message digest", 14, 0x80); //v2 + CHECK(h3.a == 0x9d25fab5a11994e2); + CHECK(h3.b == 0xea7850e77d5e00e8); + CHECK(h3.c == 0x2d465225ef42a581); + + constexpr HashType h4 = tiger("message digest", 14, 0x01); //v1 + CHECK(h4.a == 0x951a2078cbf881d9); + CHECK(h4.b == 0x1c441e754830cf0d); + CHECK(h4.c == 0xf6295aa51aca7f51); + + constexpr HashType h5 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x80); //v2 + CHECK(h5.a == 0x517bee8c22b69aea); + CHECK(h5.b == 0x8c6c06a6fc4475b7); + CHECK(h5.c == 0xcd059531e6ba5bbb); + + constexpr HashType h6 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x01); //v1 + CHECK(h6.a == 0xee8375a180a6ce8d); + CHECK(h6.b == 0x5186363c8aa32b50); + CHECK(h6.c == 0xcca849dcccfb0f89); +} From 327d93a6a459fa315792c96f85e72c39558b2599 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 00:40:57 +0200 Subject: [PATCH 32/60] Fix namespaces, copyright and magic numbers --- include/duckhandy/tiger_bt.hpp | 19 ++++++++++--------- include/duckhandy/tiger_bt.inl | 14 +++++++------- test/unit/tiger_test.cpp | 18 ++++++++++-------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/include/duckhandy/tiger_bt.hpp b/include/duckhandy/tiger_bt.hpp index f3e8a0e..6a6ea48 100644 --- a/include/duckhandy/tiger_bt.hpp +++ b/include/duckhandy/tiger_bt.hpp @@ -1,30 +1,28 @@ -/* Copyright 2015, Michele Santullo - * This file is part of DoorKeeper. +/* Copyright 2016-2021, Michele Santullo + * This file is part of "duckhandy". * - * DoorKeeper is free software: you can redistribute it and/or modify + * "duckhandy" 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. * - * DoorKeeper is distributed in the hope that it will be useful, + * "duckhandy" 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 DoorKeeper. If not, see . + * along with "duckhandy". If not, see . */ #ifndef id1E6CCE44307549A9B6C9E4E5923AC002 #define id1E6CCE44307549A9B6C9E4E5923AC002 -//#include "doorkeeper/helpers/hashing.hpp" -//#include "doorkeeper/implem/compatibility.h" #include #include #include -namespace dk { +namespace dhandy::bt { struct HashType { constexpr HashType ( uint64_t parA, uint64_t parB, uint64_t parC ) : a(parA), b(parB), c(parC) @@ -50,9 +48,12 @@ namespace dk { uint64_t c; }; + inline const constexpr char TigerPaddingV1 = 0x01; + inline const constexpr char TigerPaddingV2 = 0x80; + [[gnu::const]] constexpr HashType tiger ( const char* parStr, uint64_t parLen, char parPad ); -} //namespace dk +} //namespace dhandy::bt #include "tiger_bt.inl" diff --git a/include/duckhandy/tiger_bt.inl b/include/duckhandy/tiger_bt.inl index 80ad908..e2cf32b 100644 --- a/include/duckhandy/tiger_bt.inl +++ b/include/duckhandy/tiger_bt.inl @@ -1,18 +1,18 @@ -/* Copyright 2015, Michele Santullo - * This file is part of DoorKeeper. +/* Copyright 2016-2021, Michele Santullo + * This file is part of "duckhandy". * - * DoorKeeper is free software: you can redistribute it and/or modify + * "duckhandy" 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. * - * DoorKeeper is distributed in the hope that it will be useful, + * "duckhandy" 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 DoorKeeper. If not, see . + * along with "duckhandy". If not, see . */ #ifndef lengthof @@ -20,7 +20,7 @@ # define UNDEF_lengthof #endif -namespace dk { +namespace dhandy::bt { namespace implem { constexpr const uint64_t table[4*256] = {0x02AAB17CF7E90C5EULL, 0xAC424B03E243A8ECULL, 0x72CD5BE30DD5FCD3ULL, 0x6D019B93F6F97F3AULL, 0xCD9978FFD21F9193ULL, 0x7573A1C9708029E2ULL, @@ -490,7 +490,7 @@ namespace dk { parPad ); } -} //namespace dk +} //namespace dhandy::bt #if defined UNDEF_lengthof # undef lengthof diff --git a/test/unit/tiger_test.cpp b/test/unit/tiger_test.cpp index 9af7d89..dd695e7 100644 --- a/test/unit/tiger_test.cpp +++ b/test/unit/tiger_test.cpp @@ -19,35 +19,37 @@ #include "duckhandy/tiger_bt.hpp" TEST_CASE("Build-time Tiger hash tests", "[hash][bt][tiger]") { - using dk::tiger; - using dk::HashType; + using dhandy::bt::tiger; + using dhandy::bt::HashType; + using dhandy::bt::TigerPaddingV1; + using dhandy::bt::TigerPaddingV2; - constexpr HashType h1 = tiger("", 0, 0x80); //v2 + constexpr HashType h1 = tiger("", 0, TigerPaddingV2); CHECK(h1.a == 0x738701f675be4144); CHECK(h1.b == 0x924b374527c206c2); CHECK(h1.c == 0x419f91ef3f31a84a); - constexpr HashType h2 = tiger("", 0, 0x01); //v1 + constexpr HashType h2 = tiger("", 0, TigerPaddingV1); CHECK(h2.a == 0x24f0130c63ac9332); CHECK(h2.b == 0x16166e76b1bb925f); CHECK(h2.c == 0xf373de2d49584e7a); - constexpr HashType h3 = tiger("message digest", 14, 0x80); //v2 + constexpr HashType h3 = tiger("message digest", 14, TigerPaddingV2); CHECK(h3.a == 0x9d25fab5a11994e2); CHECK(h3.b == 0xea7850e77d5e00e8); CHECK(h3.c == 0x2d465225ef42a581); - constexpr HashType h4 = tiger("message digest", 14, 0x01); //v1 + constexpr HashType h4 = tiger("message digest", 14, TigerPaddingV1); CHECK(h4.a == 0x951a2078cbf881d9); CHECK(h4.b == 0x1c441e754830cf0d); CHECK(h4.c == 0xf6295aa51aca7f51); - constexpr HashType h5 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x80); //v2 + constexpr HashType h5 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV2); CHECK(h5.a == 0x517bee8c22b69aea); CHECK(h5.b == 0x8c6c06a6fc4475b7); CHECK(h5.c == 0xcd059531e6ba5bbb); - constexpr HashType h6 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x01); //v1 + constexpr HashType h6 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV1); CHECK(h6.a == 0xee8375a180a6ce8d); CHECK(h6.b == 0x5186363c8aa32b50); CHECK(h6.c == 0xcca849dcccfb0f89); From d068e68e75065f42af87f445004f318e4235d648 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 00:50:57 +0200 Subject: [PATCH 33/60] Replace with consteval It doesn't makes any sense to use this implementation at runtime. --- include/duckhandy/tiger_bt.hpp | 10 ++--- include/duckhandy/tiger_bt.inl | 70 +++++++++++++++++----------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/include/duckhandy/tiger_bt.hpp b/include/duckhandy/tiger_bt.hpp index 6a6ea48..e94b45b 100644 --- a/include/duckhandy/tiger_bt.hpp +++ b/include/duckhandy/tiger_bt.hpp @@ -24,18 +24,18 @@ namespace dhandy::bt { struct HashType { - constexpr HashType ( uint64_t parA, uint64_t parB, uint64_t parC ) : + consteval HashType ( uint64_t parA, uint64_t parB, uint64_t parC ) : a(parA), b(parB), c(parC) { } - constexpr HashType ( uint64_t parAP, uint64_t parA, uint64_t parBP, uint64_t parB, uint64_t parCP, uint64_t parC ) : + consteval HashType ( uint64_t parAP, uint64_t parA, uint64_t parBP, uint64_t parB, uint64_t parCP, uint64_t parC ) : a(0 == parAP ? parA : (0 == parBP ? parB : (0 == parCP ? parC : throw 0))), b(1 == parAP ? parA : (1 == parBP ? parB : (1 == parCP ? parC : throw 0))), c(2 == parAP ? parA : (2 == parBP ? parB : (2 == parCP ? parC : throw 0))) { } - constexpr HashType ( const HashType& ) = default; - constexpr uint64_t operator[] ( uint64_t parIndex ) const { + consteval HashType ( const HashType& ) = default; + consteval uint64_t operator[] ( uint64_t parIndex ) const { return (parIndex == 0 ? a : (parIndex == 1 ? b : (parIndex == 2 ? c : throw 0) @@ -52,7 +52,7 @@ namespace dhandy::bt { inline const constexpr char TigerPaddingV2 = 0x80; [[gnu::const]] - constexpr HashType tiger ( const char* parStr, uint64_t parLen, char parPad ); + consteval HashType tiger ( const char* parStr, uint64_t parLen, char parPad ); } //namespace dhandy::bt #include "tiger_bt.inl" diff --git a/include/duckhandy/tiger_bt.inl b/include/duckhandy/tiger_bt.inl index e2cf32b..4cfbb89 100644 --- a/include/duckhandy/tiger_bt.inl +++ b/include/duckhandy/tiger_bt.inl @@ -280,7 +280,7 @@ namespace dhandy::bt { 0xCB0C0708705A36A3ULL, 0xE74D14754F986044ULL, 0xCD56D9430EA8280EULL, 0xC12591D7535F5065ULL, 0xC83223F1720AEF96ULL, 0xC3A0396F7363A51FULL }; - constexpr uint64_t buff_to_uint64_with_filling (const char* parStr, const uint64_t parAvailLen) { + consteval uint64_t buff_to_uint64_with_filling (const char* parStr, const uint64_t parAvailLen) { return ( parAvailLen == 0 ? 0 @@ -291,7 +291,7 @@ namespace dhandy::bt { ); } - constexpr uint64_t buff_to_uint64_fill_ifn (const char* parStr, uint64_t parIndex, uint64_t parBuffLen, char parPad) { + consteval uint64_t buff_to_uint64_fill_ifn (const char* parStr, uint64_t parIndex, uint64_t parBuffLen, char parPad) { return (sizeof(uint64_t) * parIndex >= parBuffLen ? (sizeof(uint64_t) * parIndex == parBuffLen ? static_cast(static_cast(parPad)) @@ -309,7 +309,7 @@ namespace dhandy::bt { } struct TigerBlock { - constexpr explicit TigerBlock ( const char* parStr ) : + consteval explicit TigerBlock ( const char* parStr ) : data{ buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 0, sizeof(uint64_t)), buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 1, sizeof(uint64_t)), @@ -322,12 +322,12 @@ namespace dhandy::bt { } { } - constexpr TigerBlock ( const TigerBlock& ) = default; - constexpr TigerBlock ( uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g, uint64_t h) : + consteval TigerBlock ( const TigerBlock& ) = default; + consteval TigerBlock ( uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g, uint64_t h) : data{a, b, c, d, e, f, g, h} { } - constexpr TigerBlock ( const char* parStr, uint64_t parLen, char parPad ) : + consteval TigerBlock ( const char* parStr, uint64_t parLen, char parPad ) : data{ buff_to_uint64_fill_ifn(parStr, 0, parLen, parPad), buff_to_uint64_fill_ifn(parStr, 1, parLen, parPad), @@ -340,7 +340,7 @@ namespace dhandy::bt { } { } - constexpr TigerBlock ( const char* parStr, uint64_t parLen, char parPad, uint64_t parData7 ) : + consteval TigerBlock ( const char* parStr, uint64_t parLen, char parPad, uint64_t parData7 ) : data{ buff_to_uint64_fill_ifn(parStr, 0, parLen, parPad), buff_to_uint64_fill_ifn(parStr, 1, parLen, parPad), @@ -354,16 +354,16 @@ namespace dhandy::bt { { } - constexpr uint64_t operator[] (std::size_t parIndex) const { return (parIndex < lengthof(data) ? data[parIndex] : throw 0); } + consteval uint64_t operator[] (std::size_t parIndex) const { return (parIndex < lengthof(data) ? data[parIndex] : throw 0); } const uint64_t data[8]; }; - constexpr uint64_t gb (uint64_t r, uint64_t a) { + consteval uint64_t gb (uint64_t r, uint64_t a) { return (r >> (a * CHAR_BIT)) bitand 0xff; } - constexpr HashType round (uint64_t mul, uint64_t a, uint64_t b, uint64_t c, uint64_t x, const TigerBlock& block, const HashType& hash) { + consteval HashType round (uint64_t mul, uint64_t a, uint64_t b, uint64_t c, uint64_t x, const TigerBlock& block, const HashType& hash) { return HashType( a, hash[a] - ( @@ -382,7 +382,7 @@ namespace dhandy::bt { ); } - constexpr HashType pass (uint64_t a, uint64_t b, uint64_t c, uint64_t mul, const TigerBlock& block, const HashType& hash, uint64_t x=0) { + consteval HashType pass (uint64_t a, uint64_t b, uint64_t c, uint64_t mul, const TigerBlock& block, const HashType& hash, uint64_t x=0) { return ( 8 == x ? //if 0 == x @@ -400,25 +400,25 @@ namespace dhandy::bt { ); } - template constexpr uint64_t key_sched_op (const TigerBlock& i); - template<> constexpr uint64_t key_sched_op<0,1> (const TigerBlock& i) { return i[0] - (i[7] ^ 0xA5A5A5A5A5A5A5A5ULL); } - template<> constexpr uint64_t key_sched_op<1,1> (const TigerBlock& i) { return i[1] ^ key_sched_op<0,1>(i); } - template<> constexpr uint64_t key_sched_op<2,1> (const TigerBlock& i) { return i[2] + key_sched_op<1,1>(i); } - template<> constexpr uint64_t key_sched_op<3,1> (const TigerBlock& i) { return i[3] - (key_sched_op<2,1>(i) ^ ((~key_sched_op<1,1>(i)) << 19)); } - template<> constexpr uint64_t key_sched_op<4,1> (const TigerBlock& i) { return i[4] ^ key_sched_op<3,1>(i); } - template<> constexpr uint64_t key_sched_op<5,1> (const TigerBlock& i) { return i[5] + key_sched_op<4,1>(i); } - template<> constexpr uint64_t key_sched_op<6,1> (const TigerBlock& i) { return i[6] - (key_sched_op<5,1>(i) ^ ((~key_sched_op<4,1>(i)) >> 23)); } - template<> constexpr uint64_t key_sched_op<7,1> (const TigerBlock& i) { return i[7] ^ key_sched_op<6,1>(i); } - template<> constexpr uint64_t key_sched_op<0,2> (const TigerBlock& i) { return key_sched_op<0,1>(i) + key_sched_op<7,1>(i); } - template<> constexpr uint64_t key_sched_op<1,2> (const TigerBlock& i) { return key_sched_op<1,1>(i) - (key_sched_op<0,2>(i) ^ ((~key_sched_op<7,1>(i)) << 19)); } - template<> constexpr uint64_t key_sched_op<2,2> (const TigerBlock& i) { return key_sched_op<2,1>(i) ^ key_sched_op<1,2>(i); } - template<> constexpr uint64_t key_sched_op<3,2> (const TigerBlock& i) { return key_sched_op<3,1>(i) + key_sched_op<2,2>(i); } - template<> constexpr uint64_t key_sched_op<4,2> (const TigerBlock& i) { return key_sched_op<4,1>(i) - (key_sched_op<3,2>(i) ^ ((~key_sched_op<2,2>(i)) >> 23)); } - template<> constexpr uint64_t key_sched_op<5,2> (const TigerBlock& i) { return key_sched_op<5,1>(i) ^ key_sched_op<4,2>(i); } - template<> constexpr uint64_t key_sched_op<6,2> (const TigerBlock& i) { return key_sched_op<6,1>(i) + key_sched_op<5,2>(i); } - template<> constexpr uint64_t key_sched_op<7,2> (const TigerBlock& i) { return key_sched_op<7,1>(i) - (key_sched_op<6,2>(i) ^ 0x0123456789ABCDEFULL); } + template consteval uint64_t key_sched_op (const TigerBlock& i); + template<> consteval uint64_t key_sched_op<0,1> (const TigerBlock& i) { return i[0] - (i[7] ^ 0xA5A5A5A5A5A5A5A5ULL); } + template<> consteval uint64_t key_sched_op<1,1> (const TigerBlock& i) { return i[1] ^ key_sched_op<0,1>(i); } + template<> consteval uint64_t key_sched_op<2,1> (const TigerBlock& i) { return i[2] + key_sched_op<1,1>(i); } + template<> consteval uint64_t key_sched_op<3,1> (const TigerBlock& i) { return i[3] - (key_sched_op<2,1>(i) ^ ((~key_sched_op<1,1>(i)) << 19)); } + template<> consteval uint64_t key_sched_op<4,1> (const TigerBlock& i) { return i[4] ^ key_sched_op<3,1>(i); } + template<> consteval uint64_t key_sched_op<5,1> (const TigerBlock& i) { return i[5] + key_sched_op<4,1>(i); } + template<> consteval uint64_t key_sched_op<6,1> (const TigerBlock& i) { return i[6] - (key_sched_op<5,1>(i) ^ ((~key_sched_op<4,1>(i)) >> 23)); } + template<> consteval uint64_t key_sched_op<7,1> (const TigerBlock& i) { return i[7] ^ key_sched_op<6,1>(i); } + template<> consteval uint64_t key_sched_op<0,2> (const TigerBlock& i) { return key_sched_op<0,1>(i) + key_sched_op<7,1>(i); } + template<> consteval uint64_t key_sched_op<1,2> (const TigerBlock& i) { return key_sched_op<1,1>(i) - (key_sched_op<0,2>(i) ^ ((~key_sched_op<7,1>(i)) << 19)); } + template<> consteval uint64_t key_sched_op<2,2> (const TigerBlock& i) { return key_sched_op<2,1>(i) ^ key_sched_op<1,2>(i); } + template<> consteval uint64_t key_sched_op<3,2> (const TigerBlock& i) { return key_sched_op<3,1>(i) + key_sched_op<2,2>(i); } + template<> consteval uint64_t key_sched_op<4,2> (const TigerBlock& i) { return key_sched_op<4,1>(i) - (key_sched_op<3,2>(i) ^ ((~key_sched_op<2,2>(i)) >> 23)); } + template<> consteval uint64_t key_sched_op<5,2> (const TigerBlock& i) { return key_sched_op<5,1>(i) ^ key_sched_op<4,2>(i); } + template<> consteval uint64_t key_sched_op<6,2> (const TigerBlock& i) { return key_sched_op<6,1>(i) + key_sched_op<5,2>(i); } + template<> consteval uint64_t key_sched_op<7,2> (const TigerBlock& i) { return key_sched_op<7,1>(i) - (key_sched_op<6,2>(i) ^ 0x0123456789ABCDEFULL); } - constexpr TigerBlock key_sched (const TigerBlock& parBlock) { + consteval TigerBlock key_sched (const TigerBlock& parBlock) { return TigerBlock( key_sched_op<0,2>(parBlock), key_sched_op<1,2>(parBlock), @@ -431,7 +431,7 @@ namespace dhandy::bt { ); } - constexpr HashType finalize_tiger_step (HashType parOriginal, HashType parPartial) { + consteval HashType finalize_tiger_step (HashType parOriginal, HashType parPartial) { return HashType( parPartial.a ^ parOriginal.a, parPartial.b - parOriginal.b, @@ -439,7 +439,7 @@ namespace dhandy::bt { ); } - constexpr HashType tiger_block (const TigerBlock& parBlock, HashType parHash) { + consteval HashType tiger_block (const TigerBlock& parBlock, HashType parHash) { return finalize_tiger_step( parHash, pass(1, 2, 0, 9, key_sched(key_sched(parBlock)), @@ -450,11 +450,11 @@ namespace dhandy::bt { ); } - constexpr HashType tiger_block (const char* parStr, HashType parHash) { + consteval HashType tiger_block (const char* parStr, HashType parHash) { return tiger_block(TigerBlock(parStr), parHash); } - constexpr HashType tiger_chunk (const char* parStr, uint64_t parLen, HashType parHash) { + consteval HashType tiger_chunk (const char* parStr, uint64_t parLen, HashType parHash) { return (parLen == 0 ? //if parLen == 0 parHash @@ -464,7 +464,7 @@ namespace dhandy::bt { ); } - constexpr HashType tiger_last_chunk (const char* parStr, uint64_t parLen, uint64_t parRealLen, HashType parHash, char parPad) { + consteval HashType tiger_last_chunk (const char* parStr, uint64_t parLen, uint64_t parRealLen, HashType parHash, char parPad) { return ( parLen + 1 + ((8 - parLen - 1) bitand 7) == 64 ? tiger_block( @@ -477,7 +477,7 @@ namespace dhandy::bt { } } //namespace implem - constexpr HashType tiger (const char* parStr, uint64_t parLen, char parPad) { + consteval HashType tiger (const char* parStr, uint64_t parLen, char parPad) { return implem::tiger_last_chunk( parStr + (parLen bitand ~static_cast(0x3f)), parLen - (parLen bitand ~static_cast(0x3f)), From e8467cebe01e709c8a1325abe257afea2b3505e4 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 00:56:39 +0200 Subject: [PATCH 34/60] Remove custom lengthof() duckhandy has an implementation already --- include/duckhandy/tiger_bt.hpp | 1 + include/duckhandy/tiger_bt.inl | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/include/duckhandy/tiger_bt.hpp b/include/duckhandy/tiger_bt.hpp index e94b45b..7c07bfc 100644 --- a/include/duckhandy/tiger_bt.hpp +++ b/include/duckhandy/tiger_bt.hpp @@ -18,6 +18,7 @@ #ifndef id1E6CCE44307549A9B6C9E4E5923AC002 #define id1E6CCE44307549A9B6C9E4E5923AC002 +#include "lengthof.h" #include #include #include diff --git a/include/duckhandy/tiger_bt.inl b/include/duckhandy/tiger_bt.inl index 4cfbb89..c982962 100644 --- a/include/duckhandy/tiger_bt.inl +++ b/include/duckhandy/tiger_bt.inl @@ -15,11 +15,6 @@ * along with "duckhandy". If not, see . */ -#ifndef lengthof -# define lengthof(a) (sizeof(a) / sizeof((a)[0])) -# define UNDEF_lengthof -#endif - namespace dhandy::bt { namespace implem { constexpr const uint64_t table[4*256] = {0x02AAB17CF7E90C5EULL, 0xAC424B03E243A8ECULL, @@ -491,8 +486,3 @@ namespace dhandy::bt { ); } } //namespace dhandy::bt - -#if defined UNDEF_lengthof -# undef lengthof -# undef UNDEF_lengthof -#endif From 094f7fc67985767a0628fc47b5bebdfdeb2a58ce Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 00:57:24 +0200 Subject: [PATCH 35/60] Rename HashType to TigerHash --- include/duckhandy/tiger_bt.hpp | 10 +++++----- include/duckhandy/tiger_bt.inl | 22 +++++++++++----------- test/unit/tiger_test.cpp | 14 +++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/duckhandy/tiger_bt.hpp b/include/duckhandy/tiger_bt.hpp index 7c07bfc..7281f7e 100644 --- a/include/duckhandy/tiger_bt.hpp +++ b/include/duckhandy/tiger_bt.hpp @@ -24,18 +24,18 @@ #include namespace dhandy::bt { - struct HashType { - consteval HashType ( uint64_t parA, uint64_t parB, uint64_t parC ) : + struct TigerHash { + consteval TigerHash ( uint64_t parA, uint64_t parB, uint64_t parC ) : a(parA), b(parB), c(parC) { } - consteval HashType ( uint64_t parAP, uint64_t parA, uint64_t parBP, uint64_t parB, uint64_t parCP, uint64_t parC ) : + consteval TigerHash ( uint64_t parAP, uint64_t parA, uint64_t parBP, uint64_t parB, uint64_t parCP, uint64_t parC ) : a(0 == parAP ? parA : (0 == parBP ? parB : (0 == parCP ? parC : throw 0))), b(1 == parAP ? parA : (1 == parBP ? parB : (1 == parCP ? parC : throw 0))), c(2 == parAP ? parA : (2 == parBP ? parB : (2 == parCP ? parC : throw 0))) { } - consteval HashType ( const HashType& ) = default; + consteval TigerHash ( const TigerHash& ) = default; consteval uint64_t operator[] ( uint64_t parIndex ) const { return (parIndex == 0 ? a : (parIndex == 1 ? b : @@ -53,7 +53,7 @@ namespace dhandy::bt { inline const constexpr char TigerPaddingV2 = 0x80; [[gnu::const]] - consteval HashType tiger ( const char* parStr, uint64_t parLen, char parPad ); + consteval TigerHash tiger ( const char* parStr, uint64_t parLen, char parPad ); } //namespace dhandy::bt #include "tiger_bt.inl" diff --git a/include/duckhandy/tiger_bt.inl b/include/duckhandy/tiger_bt.inl index c982962..8ec5a6c 100644 --- a/include/duckhandy/tiger_bt.inl +++ b/include/duckhandy/tiger_bt.inl @@ -358,8 +358,8 @@ namespace dhandy::bt { return (r >> (a * CHAR_BIT)) bitand 0xff; } - consteval HashType round (uint64_t mul, uint64_t a, uint64_t b, uint64_t c, uint64_t x, const TigerBlock& block, const HashType& hash) { - return HashType( + consteval TigerHash round (uint64_t mul, uint64_t a, uint64_t b, uint64_t c, uint64_t x, const TigerBlock& block, const TigerHash& hash) { + return TigerHash( a, hash[a] - ( table[ gb(hash[c] xor block[x], 0)] xor @@ -377,7 +377,7 @@ namespace dhandy::bt { ); } - consteval HashType pass (uint64_t a, uint64_t b, uint64_t c, uint64_t mul, const TigerBlock& block, const HashType& hash, uint64_t x=0) { + consteval TigerHash pass (uint64_t a, uint64_t b, uint64_t c, uint64_t mul, const TigerBlock& block, const TigerHash& hash, uint64_t x=0) { return ( 8 == x ? //if 0 == x @@ -426,15 +426,15 @@ namespace dhandy::bt { ); } - consteval HashType finalize_tiger_step (HashType parOriginal, HashType parPartial) { - return HashType( + consteval TigerHash finalize_tiger_step (TigerHash parOriginal, TigerHash parPartial) { + return TigerHash( parPartial.a ^ parOriginal.a, parPartial.b - parOriginal.b, parPartial.c + parOriginal.c ); } - consteval HashType tiger_block (const TigerBlock& parBlock, HashType parHash) { + consteval TigerHash tiger_block (const TigerBlock& parBlock, TigerHash parHash) { return finalize_tiger_step( parHash, pass(1, 2, 0, 9, key_sched(key_sched(parBlock)), @@ -445,11 +445,11 @@ namespace dhandy::bt { ); } - consteval HashType tiger_block (const char* parStr, HashType parHash) { + consteval TigerHash tiger_block (const char* parStr, TigerHash parHash) { return tiger_block(TigerBlock(parStr), parHash); } - consteval HashType tiger_chunk (const char* parStr, uint64_t parLen, HashType parHash) { + consteval TigerHash tiger_chunk (const char* parStr, uint64_t parLen, TigerHash parHash) { return (parLen == 0 ? //if parLen == 0 parHash @@ -459,7 +459,7 @@ namespace dhandy::bt { ); } - consteval HashType tiger_last_chunk (const char* parStr, uint64_t parLen, uint64_t parRealLen, HashType parHash, char parPad) { + consteval TigerHash tiger_last_chunk (const char* parStr, uint64_t parLen, uint64_t parRealLen, TigerHash parHash, char parPad) { return ( parLen + 1 + ((8 - parLen - 1) bitand 7) == 64 ? tiger_block( @@ -472,7 +472,7 @@ namespace dhandy::bt { } } //namespace implem - consteval HashType tiger (const char* parStr, uint64_t parLen, char parPad) { + consteval TigerHash tiger (const char* parStr, uint64_t parLen, char parPad) { return implem::tiger_last_chunk( parStr + (parLen bitand ~static_cast(0x3f)), parLen - (parLen bitand ~static_cast(0x3f)), @@ -480,7 +480,7 @@ namespace dhandy::bt { implem::tiger_chunk( parStr, parLen bitand ~static_cast(0x3f), - HashType(0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL) + TigerHash{0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL} ), parPad ); diff --git a/test/unit/tiger_test.cpp b/test/unit/tiger_test.cpp index dd695e7..bdcda38 100644 --- a/test/unit/tiger_test.cpp +++ b/test/unit/tiger_test.cpp @@ -20,36 +20,36 @@ TEST_CASE("Build-time Tiger hash tests", "[hash][bt][tiger]") { using dhandy::bt::tiger; - using dhandy::bt::HashType; + using dhandy::bt::TigerHash; using dhandy::bt::TigerPaddingV1; using dhandy::bt::TigerPaddingV2; - constexpr HashType h1 = tiger("", 0, TigerPaddingV2); + constexpr TigerHash h1 = tiger("", 0, TigerPaddingV2); CHECK(h1.a == 0x738701f675be4144); CHECK(h1.b == 0x924b374527c206c2); CHECK(h1.c == 0x419f91ef3f31a84a); - constexpr HashType h2 = tiger("", 0, TigerPaddingV1); + constexpr TigerHash h2 = tiger("", 0, TigerPaddingV1); CHECK(h2.a == 0x24f0130c63ac9332); CHECK(h2.b == 0x16166e76b1bb925f); CHECK(h2.c == 0xf373de2d49584e7a); - constexpr HashType h3 = tiger("message digest", 14, TigerPaddingV2); + constexpr TigerHash h3 = tiger("message digest", 14, TigerPaddingV2); CHECK(h3.a == 0x9d25fab5a11994e2); CHECK(h3.b == 0xea7850e77d5e00e8); CHECK(h3.c == 0x2d465225ef42a581); - constexpr HashType h4 = tiger("message digest", 14, TigerPaddingV1); + constexpr TigerHash h4 = tiger("message digest", 14, TigerPaddingV1); CHECK(h4.a == 0x951a2078cbf881d9); CHECK(h4.b == 0x1c441e754830cf0d); CHECK(h4.c == 0xf6295aa51aca7f51); - constexpr HashType h5 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV2); + constexpr TigerHash h5 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV2); CHECK(h5.a == 0x517bee8c22b69aea); CHECK(h5.b == 0x8c6c06a6fc4475b7); CHECK(h5.c == 0xcd059531e6ba5bbb); - constexpr HashType h6 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV1); + constexpr TigerHash h6 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV1); CHECK(h6.a == 0xee8375a180a6ce8d); CHECK(h6.b == 0x5186363c8aa32b50); CHECK(h6.c == 0xcca849dcccfb0f89); From a675624cab4880818bdeeee5e2438e90d80916f4 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 12:01:01 +0200 Subject: [PATCH 36/60] Add case sensitivity support to sse conversion --- include/duckhandy/implem/int_conv.hpp | 34 +++++++++++++++++++------ test/unit/int_conv_test.cpp | 36 +++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 11cceb0..3396003 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -18,7 +18,8 @@ #ifndef id4754A95F12BE4ADEA65642A056A51907 #define id4754A95F12BE4ADEA65642A056A51907 -#include "duckhandy/implem/reversed_sized_array_bt.hpp" +#include "reversed_sized_array_bt.hpp" +#include "../has_method.hpp" #include #include #include @@ -51,6 +52,14 @@ namespace dhandy { } } //unnamed namespace + //Used for checking ASCIITranslator::AltLetter + define_has_enum(AltLetter, AltLetter); + + template ::value != 0> + inline auto g_AltLetterOrZero = Tr::AltLetter; + template + inline auto g_AltLetterOrZero = Tr::NullChar; + template T to_integer_sse (const C* s, std::size_t l); @@ -202,7 +211,7 @@ namespace dhandy { }; template - struct AryConversion::value and not std::is_same::value and sizeof(I) <= sizeof(std::uint32_t)>::type> { + struct AryConversion::value and not std::is_same::value and sizeof(I) <= sizeof(std::uint32_t)>::type> { constexpr static const bool is_sse = true; template static I from_ary (C* beg, C* end) { return to_integer_sse(beg, end - beg); } }; @@ -246,13 +255,24 @@ namespace dhandy { __m128i factor = _mm_set_epi32(base3, base2, base1, 1); __m128i res = _mm_set1_epi32(0); const __m128i char_0 = _mm_set1_epi32(Tr::FirstDigit); - const __m128i char_a = _mm_set1_epi32(Tr::FirstLetter); + const __m128i char_befo_a = _mm_set1_epi32(Tr::FirstLetter - 1); + const __m128i char_past_f = _mm_set1_epi32(Tr::FirstLetter + Base - 10); std::size_t idx = 0; const std::size_t cap = l bitand -4; do { const __m128i digits = _mm_set_epi32(s[cap - idx - 3 - 1], s[cap - idx - 2 - 1], s[cap - idx - 1 - 1], s[cap - idx - 0 - 1]); - const __m128i mask = _mm_cmplt_epi32(digits, char_a); - const __m128i addend = _mm_add_epi32(_mm_andnot_si128(mask, _mm_sub_epi32(char_a, _mm_set1_epi32(10))), _mm_and_si128(mask, char_0)); + __m128i mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_a), _mm_cmplt_epi32(digits, char_past_f)); + __m128i offs = _mm_and_si128(mask, _mm_set1_epi32(Tr::FirstLetter - 10)); + + if constexpr (HasAltLetterEnum::value) { + const __m128i char_befo_A = _mm_set1_epi32(g_AltLetterOrZero - 1); + const __m128i char_past_F = _mm_set1_epi32(g_AltLetterOrZero + Base - 10); + const __m128i alt_mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_A), _mm_cmplt_epi32(digits, char_past_F)); + const __m128i alt_offs = _mm_and_si128(alt_mask, _mm_set1_epi32(g_AltLetterOrZero - 10)); + offs = _mm_add_epi32(alt_offs, offs); + mask = _mm_or_si128(mask, alt_mask); + } + const __m128i addend = _mm_add_epi32(offs, _mm_andnot_si128(mask, char_0)); res = _mm_add_epi32(res, muly(_mm_sub_epi32(digits, addend), factor)); factor = muly(factor, _mm_set1_epi32(base4)); idx += 4; @@ -261,7 +281,7 @@ namespace dhandy { { res = _mm_add_epi32(res, _mm_srli_si128(res, 8)); res = _mm_add_epi32(res, _mm_srli_si128(res, 4)); - const std::array scale {1, base1, base2, base3}; + constexpr const std::array scale {1, base1, base2, base3}; return negated_ifn(to_integer_sse(s + idx, l - idx) + _mm_cvtsi128_si32(res) * scale[l - idx], was_negative); } } @@ -272,9 +292,9 @@ namespace dhandy { template struct ASCIITranslator { typedef C char_type; - static const constexpr bool BehavesLikeASCII = true; static const constexpr C FirstDigit = FDigit; static const constexpr C FirstLetter = FLetter; + //static const constexpr C AltLetter = FAltLetter; static const constexpr C Plus = CPlus; static const constexpr C Minus = CMinus; static const constexpr C NullChar = CNull; diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index cfe9276..f5eef34 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -29,6 +29,17 @@ template using int_info_16 = dhandy::implem::int_info; template using int_info_2 = dhandy::implem::int_info; namespace { + template + struct ASCIITranslatorIns : public dhandy::ASCIITranslator { + static const constexpr char AltLetter = 'A'; + static constexpr int from_digit (char dig) { + if (dig >= FirstLetter and dig <= FirstLetter + Base - 10 - 1) + return dig - FirstLetter + 10; + else + return dig - AltLetter + 10; + } + }; + template void AryConversionTestHelper (const std::string_view& s, T expected, bool expect_sse) { using AryConversion = dhandy::implem::AryConversion, false>; @@ -42,6 +53,13 @@ namespace { CHECK(AryConversion::is_sse == expect_sse); CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); } + + template + void AryConversionTestHelperIns (const std::string_view& s, T expected, bool expect_sse) { + using AryConversion = dhandy::implem::AryConversion, false>; + CHECK(AryConversion::is_sse == expect_sse); + CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected); + } } //unnamed namespace TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") { @@ -170,6 +188,15 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { AryConversionTestHelper("-50000", -50000, sizeof(signed int) <= sizeof(std::uint32_t)); AryConversionTestHelper("-1", -1, false); AryConversionTestHelper("-510123123123", -510123123123, false); + + //case insensitive SSE conversions + AryConversionTestHelperIns("7FfFfFfF", 0x7fffffff, true); + AryConversionTestHelperIns("AbCdEf01", 0xabcdef01, true); + AryConversionTestHelperIns("aBcDeF01", 0xabcdef01, true); + AryConversionTestHelperIns("Ff", 0xff, true); + AryConversionTestHelperIns("AfBe", 0xafbe, true); + AryConversionTestHelperIns("aAb", 0xaab, true); + AryConversionTestHelperIns("aAbBc", 0xaabbc, true); } TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") { @@ -195,3 +222,12 @@ TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") constexpr auto int4 = int_conv(integral_constant{}); CHECK("-256" == int4); } + +TEST_CASE ("Try int conv with non-char", "[i2s][int_conv]") { + using dhandy::int_to_ary; + using dhandy::ASCIITranslator; + + std::wstring_view exp1(L"235713"); + auto val1 = int_to_ary>(235713).to_string_view(); + CHECK(exp1 == val1); +} From 938c8fa9a406f94feec4f5df63833279c289a46d Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 16:44:06 +0200 Subject: [PATCH 37/60] Make code a bit more readable Changed so that int_conv() called on a non-constexpr doesn't compiler anymore (because code would try to go through a consteval method). It wouldn't work anyways as the returned value would be always garbage. If you want a string_view then you must either give a constexpr input value or you must call int_conv_raw and call to_string_view() yourself. This is better than throwing a runtime exception (which was working ok btw). All the SafeRetVal stuff is not needed anymore. Also no need for all that confusing sfinae, I can just use a bool FromInt and specialise on that. --- include/duckhandy/int_conv.hpp | 40 +++++++++++++++------------------- test/unit/int_conv_test.cpp | 27 ++++++++++++++++++++++- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index 6fb4b16..b7edd46 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -22,11 +22,10 @@ #include #include #include -#include namespace dhandy { namespace implem { - template + template > struct IntConv; template @@ -35,24 +34,21 @@ namespace dhandy { template using IntConvStringView = std::basic_string_view; - template - struct IntConv, IntConvString>, F, SafeRetval, Tr> { + template + struct IntConv, F, Tr, true> { static IntConvString conv (const F& in) { auto retval = dhandy::int_to_ary(in); return IntConvString{retval.begin(), retval.end() - 1}; } }; - template - struct IntConv, IntConvStringView>, F, SafeRetval, Tr> { - constexpr static IntConvStringView conv (const F& in) { - if (std::is_constant_evaluated() or not SafeRetval) - return dhandy::int_to_ary(in).to_string_view(); - else - throw std::logic_error("Only callable in a constexpr context, call int_conv_temporary() instead if you know what you're doing"); + template + struct IntConv, F, Tr, true> { + consteval static IntConvStringView conv (const F& in) { + return dhandy::int_to_ary(in).to_string_view(); } }; - template - struct IntConv, IntConvString>, SafeRetval, Tr> { + template + struct IntConv, Tr, false> { constexpr static T conv (const IntConvString& in) { return dhandy::ary_to_int( in.data(), @@ -60,8 +56,8 @@ namespace dhandy { ); } }; - template - struct IntConv, IntConvStringView>, SafeRetval, Tr> { + template + struct IntConv, Tr, false> { constexpr static T conv (const IntConvStringView& in) { return dhandy::ary_to_int( in.data(), @@ -69,8 +65,8 @@ namespace dhandy { ); } }; - template - struct IntConv, SafeRetval, Tr> { + template + struct IntConv, Tr, FromInt> { constexpr static T conv (const std::integral_constant&) { return dhandy::buildtime_int_to_ary().to_string_view(); } @@ -80,14 +76,14 @@ namespace dhandy { template constexpr inline To int_conv (const From& from, bool all_caps=false) { if (all_caps) - return implem::IntConv>::conv(from); + return implem::IntConv>::conv(from); else - return implem::IntConv>::conv(from); + return implem::IntConv>::conv(from); } - template - constexpr inline To int_conv_temporary (const From& from) { - return implem::IntConv>::conv(from); + template + inline auto int_conv_raw (const From& from) { + return int_to_ary>(from); } } //namespace dhandy diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index f5eef34..d187ae7 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -23,6 +23,7 @@ #include #include #include +#include template using int_info_10 = dhandy::implem::int_info; template using int_info_16 = dhandy::implem::int_info; @@ -142,7 +143,7 @@ TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") { { //Try a random test, which should not compile as constexpr std::mt19937 gen; - gen.seed(1234); + gen.seed(std::time(nullptr)); for (int z = 0; z < 10; ++z) { const int num = gen(); CHECK(int_to_ary(num) == std::to_string(num)); @@ -199,6 +200,30 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { AryConversionTestHelperIns("aAbBc", 0xaabbc, true); } +TEST_CASE ("Check string_view conversions work as expected", "[i2s][int_conv]") { + using dhandy::int_conv; + using dhandy::int_conv_raw; + using std::string_view; + using std::integral_constant; + using std::string; + + constexpr auto str71 = int_conv(integral_constant{}); + CHECK("71" == str71); + + { + //test random number to force non-constexpr + std::mt19937 gen; + gen.seed(std::time(nullptr)); + const int num = gen(); + + const string num_str {int_conv_raw(num).to_string_view()}; + CHECK(num_str == std::to_string(num)); + } + + const auto str123 = int_conv(123); + CHECK("123" == str123); +} + TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") { using dhandy::int_conv; using std::string_view; From 199db7640eb36ac347e8f3a25b89ab16333a3400 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 16:47:48 +0200 Subject: [PATCH 38/60] Add support for int_conv() --- .../implem/reversed_sized_array_bt.hpp | 16 ++++++++++++++++ include/duckhandy/int_conv.hpp | 18 ++++++++++++++++++ test/unit/int_conv_test.cpp | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index 30fcc80..225c817 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -26,6 +26,7 @@ # include # include #endif +#include namespace dhandy { template @@ -33,6 +34,8 @@ namespace dhandy { static_assert(S > 0, "This container requires size to be at least 1"); static_assert(std::is_trivial::value, "Only use this container with trivial types"); public: + constexpr static const std::size_t capacity = S; + using iterator = typename std::array::iterator; constexpr ReversedSizedArray() = default; ~ReversedSizedArray() = default; @@ -49,6 +52,7 @@ namespace dhandy { template constexpr V to() const { return V(data(), size() - (not empty() and not back() ? 1 : 0)); } + constexpr auto to_tuple() const; #if !defined(INT_CONV_WITHOUT_HELPERS) constexpr std::basic_string_view to_string_view() const { return to>(); } @@ -65,6 +69,13 @@ namespace dhandy { std::size_t m_curr {S - 1}; }; + namespace implem { + template + constexpr auto elements_or_empty_to_tuple (const std::array& elems, std::size_t from_idx, std::index_sequence) { + return std::make_tuple((from_idx + Indices < S ? elems[from_idx + Indices] : T{})...); + } + } //namespace implem + #if !defined(INT_CONV_WITHOUT_HELPERS) template inline @@ -73,6 +84,11 @@ namespace dhandy { return stream; } #endif + + template + constexpr auto ReversedSizedArray::to_tuple() const { + return implem::elements_or_empty_to_tuple(m_data, m_curr + 1, std::make_index_sequence{}); + } } //namespace dhandy #endif diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index b7edd46..1e31501 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace dhandy { namespace implem { @@ -47,6 +48,23 @@ namespace dhandy { return dhandy::int_to_ary(in).to_string_view(); } }; + template + struct IntConv, F, Tr, true> { + private: + template + constexpr static std::array to_array (const std::tuple& vals, std::index_sequence) { + return std::array{std::get(vals)...}; + } + public: + constexpr static std::array conv (const F& in) { + return to_array( + dhandy::int_to_ary(in).to_tuple(), + std::make_index_sequence< + std::min(decltype(dhandy::int_to_ary(in))::capacity, N) + >{} + ); + } + }; template struct IntConv, Tr, false> { constexpr static T conv (const IntConvString& in) { diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index d187ae7..1bd46ce 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -224,6 +224,23 @@ TEST_CASE ("Check string_view conversions work as expected", "[i2s][int_conv]") CHECK("123" == str123); } +TEST_CASE ("Check std::array conversion works as expected", "[i2s][int_conv]") { + using std::array; + using dhandy::int_conv; + + auto arr748 = int_conv>(748); + CHECK(arr748[0] == '7'); + CHECK(arr748[1] == '4'); + CHECK(arr748[2] == '8'); + + auto arr19000 = int_conv>(19); + CHECK(arr19000[0] == '1'); + CHECK(arr19000[1] == '9'); + CHECK(arr19000[2] == '\0'); + CHECK(arr19000[3] == '\0'); + CHECK(arr19000[4] == '\0'); +} + TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") { using dhandy::int_conv; using std::string_view; From 420257f5788fd52c346f56a17fb1e6a7079a8b32 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 17:07:55 +0200 Subject: [PATCH 39/60] Use parameter instead of assuming 10 numeric digits --- include/duckhandy/implem/int_conv.hpp | 17 +++++++++-------- test/unit/int_conv_test.cpp | 26 ++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 3396003..6a901e0 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -256,19 +256,19 @@ namespace dhandy { __m128i res = _mm_set1_epi32(0); const __m128i char_0 = _mm_set1_epi32(Tr::FirstDigit); const __m128i char_befo_a = _mm_set1_epi32(Tr::FirstLetter - 1); - const __m128i char_past_f = _mm_set1_epi32(Tr::FirstLetter + Base - 10); + const __m128i char_past_f = _mm_set1_epi32(Tr::FirstLetter + Base - Tr::DigitCount); std::size_t idx = 0; const std::size_t cap = l bitand -4; do { const __m128i digits = _mm_set_epi32(s[cap - idx - 3 - 1], s[cap - idx - 2 - 1], s[cap - idx - 1 - 1], s[cap - idx - 0 - 1]); __m128i mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_a), _mm_cmplt_epi32(digits, char_past_f)); - __m128i offs = _mm_and_si128(mask, _mm_set1_epi32(Tr::FirstLetter - 10)); + __m128i offs = _mm_and_si128(mask, _mm_set1_epi32(Tr::FirstLetter - Tr::DigitCount)); if constexpr (HasAltLetterEnum::value) { const __m128i char_befo_A = _mm_set1_epi32(g_AltLetterOrZero - 1); - const __m128i char_past_F = _mm_set1_epi32(g_AltLetterOrZero + Base - 10); + const __m128i char_past_F = _mm_set1_epi32(g_AltLetterOrZero + Base - Tr::DigitCount); const __m128i alt_mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_A), _mm_cmplt_epi32(digits, char_past_F)); - const __m128i alt_offs = _mm_and_si128(alt_mask, _mm_set1_epi32(g_AltLetterOrZero - 10)); + const __m128i alt_offs = _mm_and_si128(alt_mask, _mm_set1_epi32(g_AltLetterOrZero - Tr::DigitCount)); offs = _mm_add_epi32(alt_offs, offs); mask = _mm_or_si128(mask, alt_mask); } @@ -289,7 +289,7 @@ namespace dhandy { } } //namespace implem - template + template struct ASCIITranslator { typedef C char_type; static const constexpr C FirstDigit = FDigit; @@ -298,18 +298,19 @@ namespace dhandy { static const constexpr C Plus = CPlus; static const constexpr C Minus = CMinus; static const constexpr C NullChar = CNull; + static const constexpr unsigned int DigitCount = DCount; static constexpr C to_digit (unsigned int num) { - return (num <= 9 ? + return (num < DigitCount ? static_cast(num + FirstDigit) : - static_cast(num + FirstLetter - 10) + static_cast(num + FirstLetter - DigitCount) ); } static constexpr int from_digit (C dig) { return (dig < FirstLetter ? dig - FirstDigit : - dig - FirstLetter + 10 + dig - FirstLetter + DigitCount ); } }; diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index 1bd46ce..f79115f 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -63,7 +63,7 @@ namespace { } } //unnamed namespace -TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") { +TEST_CASE ("Check int to char array conversions", "[i2s][int_conv]") { using dhandy::int_to_ary; using dhandy::bt::string; using dhandy::bt::make_string; @@ -157,7 +157,7 @@ TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") { } } -TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { +TEST_CASE ("Check char array to int conversions", "[s2i][int_conv]") { AryConversionTestHelper("0", 0, true); AryConversionTestHelper("0", 0, true); AryConversionTestHelper("0", 0, true); @@ -200,7 +200,7 @@ TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") { AryConversionTestHelperIns("aAbBc", 0xaabbc, true); } -TEST_CASE ("Check string_view conversions work as expected", "[i2s][int_conv]") { +TEST_CASE ("Check string_view conversions work as expected", "[s2i][int_conv]") { using dhandy::int_conv; using dhandy::int_conv_raw; using std::string_view; @@ -265,7 +265,7 @@ TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") CHECK("-256" == int4); } -TEST_CASE ("Try int conv with non-char", "[i2s][int_conv]") { +TEST_CASE ("Try int conv with non-char", "[s2i][int_conv]") { using dhandy::int_to_ary; using dhandy::ASCIITranslator; @@ -273,3 +273,21 @@ TEST_CASE ("Try int conv with non-char", "[i2s][int_conv]") { auto val1 = int_to_ary>(235713).to_string_view(); CHECK(exp1 == val1); } + +TEST_CASE ("Check some fancy conversions", "[i2s][int_conv]") { + using dhandy::int_to_ary; + using std::string; + using MyFancyTranslator = dhandy::ASCIITranslator; + + string str1 = int_to_ary(3).to_string(); + CHECK("3" == str1); + + string str2 = int_to_ary(5).to_string(); + CHECK("b" == str2); + + string str3 = int_to_ary(11).to_string(); + CHECK("11" == str3); + + string str4 = int_to_ary(537).to_string(); + CHECK("b3d" == str4); +} From 9dbabcb5c4780e24681c946098d4d58438881923 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 29 May 2021 22:51:49 +0200 Subject: [PATCH 40/60] Working on optimisation but I'm still losing to std::to_string() --- CMakeLists.txt | 4 ++ include/duckhandy/implem/int_conv.hpp | 53 ++++++++++++++----- .../implem/reversed_sized_array_bt.hpp | 3 ++ include/duckhandy/int_conv.hpp | 6 +-- test/unit/CMakeLists.txt | 2 +- test/unit/int_conv_test.cpp | 4 +- 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1896d76..bd1965b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,10 @@ target_compile_definitions(${PROJECT_NAME} INTERFACE SPROUT_USE_TEMPLATE_ALIASES ) +target_compile_options(${PROJECT_NAME} + INTERFACE -mprfchw +) + if (BUILD_TESTING) add_subdirectory(test/unit) endif() diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 6a901e0..9c6a661 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -104,11 +104,26 @@ namespace dhandy { template [[gnu::pure,gnu::always_inline]] - static constexpr L abs(L in) { return (not BecomesUnsigned and std::numeric_limits::is_signed and in < L(0) ? -in : in); } + static constexpr L abs(L v); [[gnu::pure,gnu::always_inline]] static constexpr CastedType cast (I in) { return static_cast(in); } }; + template + template + [[gnu::const,gnu::always_inline]] + inline constexpr L NumberAdaptation::abs(L v) { + if constexpr (not BecomesUnsigned and std::numeric_limits::is_signed) { + //https://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs + const L mask = v >> (sizeof(L) * CHAR_BIT - 1); + const UnsignedType r = (v + mask) ^ mask; + return static_cast(r); + } + else { + return v; + } + } + template struct IntConversion { static constexpr RevArray to_ary (I in) { @@ -156,18 +171,21 @@ namespace dhandy { const bool was_negative = implem::is_negative(in); RetType arr; + if (not std::is_constant_evaluated()) + __builtin_prefetch(arr.base_ptr(), 1, 3); arr.push_front(Tr::NullChar); - while (Num::abs(in) >= static_cast(100)) { - const auto index = (Num::abs(in) % 100) * 2; + in = Num::abs(in); + while (in >= static_cast(100)) { + const auto index = (in % 100) * 2; arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); in = static_cast(in / static_cast(100)); }; - if (Num::abs(in) < static_cast(10)) { - arr.push_front(Tr::to_digit(static_cast(Num::abs(in)))); + if (in < static_cast(10)) { + arr.push_front(Tr::to_digit(static_cast(in))); } else { - const auto index = Num::abs(in) * 2; + const auto index = in * 2; arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); } @@ -301,17 +319,24 @@ namespace dhandy { static const constexpr unsigned int DigitCount = DCount; static constexpr C to_digit (unsigned int num) { - return (num < DigitCount ? - static_cast(num + FirstDigit) : - static_cast(num + FirstLetter - DigitCount) - ); + constexpr const C ret[2] = {FirstDigit, FirstLetter - DigitCount}; +#if 0 + //https://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching + const bool f = num >= DigitCount; + constexpr const unsigned int m = 1; + const unsigned int w = (-f & m); +#else + const auto w = (DigitCount - 1 - num) >> (sizeof(unsigned int) * CHAR_BIT - 1); +#endif + return num + ret[w]; } static constexpr int from_digit (C dig) { - return (dig < FirstLetter ? - dig - FirstDigit : - dig - FirstLetter + DigitCount - ); + //return (dig < FirstLetter ? dig - FirstDigit : dig - FirstLetter + DigitCount); + typedef typename std::make_unsigned::type UC; + constexpr const C ret[2] = {FirstLetter - DigitCount, FirstDigit}; + const auto w = static_cast(dig - FirstLetter) >> (sizeof(UC) * CHAR_BIT - 1); + return dig - ret[w]; } }; template diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index 225c817..e31641d 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -46,6 +46,7 @@ namespace dhandy { constexpr T& operator[] (std::size_t idx) { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; } constexpr void push_front (const T& itm) { if (size() == S) throw std::length_error("ReversedSizedArray is full"); m_data[m_curr--] = itm; } constexpr const T* data() const { return m_data.data() + m_curr + 1; } + constexpr const T* base_ptr() const { return m_data.data(); } constexpr iterator begin() { return m_data.begin() + m_curr + 1; } constexpr iterator end() { return m_data.end(); } constexpr const T& back() const { return *(m_data.data() + S - 1); } @@ -62,6 +63,8 @@ namespace dhandy { bool operator!= (const std::basic_string& other) const { return not operator==(other); } bool operator== (const T* other) const { return to_string_view() == std::basic_string_view(other); } bool operator!= (const T* other) const { return not operator==(other); } + + std::string to_string() const { return to>(); } #endif private: diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index 1e31501..69fa51c 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -91,9 +91,9 @@ namespace dhandy { }; } //namespace implem - template - constexpr inline To int_conv (const From& from, bool all_caps=false) { - if (all_caps) + template + constexpr inline To int_conv (const From& from, std::integral_constant = std::integral_constant{}) { + if constexpr (AllCaps) return implem::IntConv>::conv(from); else return implem::IntConv>::conv(from); diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 049d6da..4e5c5f2 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -1,9 +1,9 @@ project(dhandy_unit_test CXX) add_executable(${PROJECT_NAME} + int_conv_test.cpp main.cpp endianness_test.cpp - int_conv_test.cpp reversed_sized_array_test.cpp bitfield_pack_test.cpp resource_pool_test.cpp diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index f79115f..9b3de00 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -266,11 +266,11 @@ TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") } TEST_CASE ("Try int conv with non-char", "[s2i][int_conv]") { - using dhandy::int_to_ary; + using dhandy::buildtime_int_to_ary; using dhandy::ASCIITranslator; std::wstring_view exp1(L"235713"); - auto val1 = int_to_ary>(235713).to_string_view(); + auto val1 = buildtime_int_to_ary>().to_string_view(); CHECK(exp1 == val1); } From e3140a3addb9ae837f191982a086419bb6e74e11 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 18:58:28 +0200 Subject: [PATCH 41/60] Trying with a smaller lookup, still slower than std::to_string --- include/duckhandy/implem/int_conv.hpp | 30 +++++++------- speed_test_int_conv.cpp | 56 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 speed_test_int_conv.cpp diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 9c6a661..ded9174 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -159,14 +159,13 @@ namespace dhandy { using RetType = RevArray; using Num = implem::NumberAdaptation; - const constexpr char lookup[200] = { - 0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,1,0,1,1,1,2,1,3,1,4, - 1,5,1,6,1,7,1,8,1,9,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9, - 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,4,0,4,1,4,2,4,3,4,4, - 4,5,4,6,4,7,4,8,4,9,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9, - 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,7,0,7,1,7,2,7,3,7,4, - 7,5,7,6,7,7,7,8,7,9,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9, - 9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9 + //How to build this lookup: 1) write numbers 0, 10, 20..., 90 + //in binary; 2) take the lowest 5 bits, div by 2 and write as + //decimal; 3) divide by 2; 4) the result is the position in the + //below array that should be filled in with the leading digit + //from the original 0-90 number + constexpr const char lookup[16] = { + 0, 0, 0, 7, 4, 1, 0, 0, 8, 5, 2, 0, 0, 9, 6, 3 }; const bool was_negative = implem::is_negative(in); @@ -176,18 +175,21 @@ namespace dhandy { arr.push_front(Tr::NullChar); in = Num::abs(in); while (in >= static_cast(100)) { - const auto index = (in % 100) * 2; - arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); - arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); + const auto last_two = in % 100; + const auto digit_low = in % 10; in = static_cast(in / static_cast(100)); + const auto digit_high = lookup[((last_two - digit_low) >> 1) & 0xF]; + arr.push_front(Tr::to_digit(static_cast(digit_low))); + arr.push_front(Tr::to_digit(static_cast(digit_high))); }; if (in < static_cast(10)) { arr.push_front(Tr::to_digit(static_cast(in))); } else { - const auto index = in * 2; - arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); - arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); + const auto digit_low = in % 10; + const auto digit_high = lookup[((in - digit_low) >> 1) & 0xF]; + arr.push_front(Tr::to_digit(static_cast(digit_low))); + arr.push_front(Tr::to_digit(static_cast(digit_high))); } if (was_negative) arr.push_front(Tr::Minus); diff --git a/speed_test_int_conv.cpp b/speed_test_int_conv.cpp new file mode 100644 index 0000000..d62c945 --- /dev/null +++ b/speed_test_int_conv.cpp @@ -0,0 +1,56 @@ +#include "duckhandy/int_conv.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace { +template +void run_with_timing ( + const std::string& test_name, + const std::vector& src, + std::vector& dst, + Conv&& conv_func +) { + dst.clear(); + dst.resize(src.size()); + std::cout << test_name << "...\n"; + const std::size_t count = src.size(); + + const auto t0 = std::chrono::high_resolution_clock::now(); + for (std::size_t z = 0; z < count; ++z) { + dst[z] = conv_func(src[z]); + } + const auto t1 = std::chrono::high_resolution_clock::now(); + + std::chrono::duration duration = t1 - t0; + std::cout << count << " conversions completed in " << duration.count() << " seconds\n"; +} +} //unnamed namespace + +int main() { + using dhandy::int_conv; + constexpr const std::size_t count = 50'000'000; + + std::vector nums; + std::vector strings; + std::mt19937 gen; + + std::cout << "Setting up data...\n"; + + nums.resize(count); + strings.reserve(count); + gen.seed(std::time(nullptr)); + + std::cout << "Generating " << count << " random values...\n"; + std::generate(nums.begin(), nums.end(), gen); + + run_with_timing("Conversions with std::to_string", nums, strings, [](unsigned int n) { return std::to_string(n); }); + run_with_timing("AryConversion with dhandy::int_conv", nums, strings, [](unsigned int n) { return int_conv(n); }); + + std::cout << "All done, bye!\n"; + return 0; +} From a68815b3cdabfefc27bf8a962fbc00b2f501d81d Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 20:01:34 +0200 Subject: [PATCH 42/60] Same conversion but without any lookup --- include/duckhandy/implem/int_conv.hpp | 12 ++---------- speed_test_int_conv.cpp | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index ded9174..2fd9239 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -159,14 +159,6 @@ namespace dhandy { using RetType = RevArray; using Num = implem::NumberAdaptation; - //How to build this lookup: 1) write numbers 0, 10, 20..., 90 - //in binary; 2) take the lowest 5 bits, div by 2 and write as - //decimal; 3) divide by 2; 4) the result is the position in the - //below array that should be filled in with the leading digit - //from the original 0-90 number - constexpr const char lookup[16] = { - 0, 0, 0, 7, 4, 1, 0, 0, 8, 5, 2, 0, 0, 9, 6, 3 - }; const bool was_negative = implem::is_negative(in); RetType arr; @@ -178,7 +170,7 @@ namespace dhandy { const auto last_two = in % 100; const auto digit_low = in % 10; in = static_cast(in / static_cast(100)); - const auto digit_high = lookup[((last_two - digit_low) >> 1) & 0xF]; + const auto digit_high = last_two / 10; arr.push_front(Tr::to_digit(static_cast(digit_low))); arr.push_front(Tr::to_digit(static_cast(digit_high))); }; @@ -187,7 +179,7 @@ namespace dhandy { } else { const auto digit_low = in % 10; - const auto digit_high = lookup[((in - digit_low) >> 1) & 0xF]; + const auto digit_high = (in / 10) % 10; arr.push_front(Tr::to_digit(static_cast(digit_low))); arr.push_front(Tr::to_digit(static_cast(digit_high))); } diff --git a/speed_test_int_conv.cpp b/speed_test_int_conv.cpp index d62c945..063ce95 100644 --- a/speed_test_int_conv.cpp +++ b/speed_test_int_conv.cpp @@ -33,7 +33,7 @@ void run_with_timing ( int main() { using dhandy::int_conv; - constexpr const std::size_t count = 50'000'000; + constexpr const std::size_t count = 70'000'000; std::vector nums; std::vector strings; From a171faa95d30c5d84a7aa46620ace38c21e933de Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 20:02:07 +0200 Subject: [PATCH 43/60] Revert lookup removal, but keep the speed test cpp This reverts commit 4f1c0f8d6df21d7c3b404d41512bba0b60ba7689. --- include/duckhandy/implem/int_conv.hpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 2fd9239..9c6a661 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -159,6 +159,15 @@ namespace dhandy { using RetType = RevArray; using Num = implem::NumberAdaptation; + const constexpr char lookup[200] = { + 0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,1,0,1,1,1,2,1,3,1,4, + 1,5,1,6,1,7,1,8,1,9,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9, + 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,4,0,4,1,4,2,4,3,4,4, + 4,5,4,6,4,7,4,8,4,9,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9, + 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,7,0,7,1,7,2,7,3,7,4, + 7,5,7,6,7,7,7,8,7,9,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9, + 9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9 + }; const bool was_negative = implem::is_negative(in); RetType arr; @@ -167,21 +176,18 @@ namespace dhandy { arr.push_front(Tr::NullChar); in = Num::abs(in); while (in >= static_cast(100)) { - const auto last_two = in % 100; - const auto digit_low = in % 10; + const auto index = (in % 100) * 2; + arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); + arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); in = static_cast(in / static_cast(100)); - const auto digit_high = last_two / 10; - arr.push_front(Tr::to_digit(static_cast(digit_low))); - arr.push_front(Tr::to_digit(static_cast(digit_high))); }; if (in < static_cast(10)) { arr.push_front(Tr::to_digit(static_cast(in))); } else { - const auto digit_low = in % 10; - const auto digit_high = (in / 10) % 10; - arr.push_front(Tr::to_digit(static_cast(digit_low))); - arr.push_front(Tr::to_digit(static_cast(digit_high))); + const auto index = in * 2; + arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); + arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); } if (was_negative) arr.push_front(Tr::Minus); From c9b2d364912247711f158c77a9874a2aab27f974 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 21:52:33 +0200 Subject: [PATCH 44/60] Pull lookup out. This makes the function run faster --- include/duckhandy/implem/int_conv.hpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index 9c6a661..ca59424 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -155,19 +155,22 @@ namespace dhandy { template struct IntConversion::value and not std::is_same::value>::type> { + private: + static const constexpr char lookup[200] = { + 0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,1,0,1,1,1,2,1,3,1,4, + 1,5,1,6,1,7,1,8,1,9,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9, + 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,4,0,4,1,4,2,4,3,4,4, + 4,5,4,6,4,7,4,8,4,9,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9, + 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,7,0,7,1,7,2,7,3,7,4, + 7,5,7,6,7,7,7,8,7,9,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9, + 9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9 + }; + + public: static constexpr RevArray to_ary (I in) { using RetType = RevArray; using Num = implem::NumberAdaptation; - const constexpr char lookup[200] = { - 0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,1,0,1,1,1,2,1,3,1,4, - 1,5,1,6,1,7,1,8,1,9,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9, - 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,4,0,4,1,4,2,4,3,4,4, - 4,5,4,6,4,7,4,8,4,9,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9, - 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,7,0,7,1,7,2,7,3,7,4, - 7,5,7,6,7,7,7,8,7,9,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9, - 9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9 - }; const bool was_negative = implem::is_negative(in); RetType arr; From 180f79fae953d7305c569d700e81fdde70a97cd6 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 21:54:46 +0200 Subject: [PATCH 45/60] Replace std::array with C array --- .../implem/reversed_sized_array_bt.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index e31641d..9085b00 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -18,7 +18,6 @@ #ifndef idFC25566D624140559C54B39FFFE52F04 #define idFC25566D624140559C54B39FFFE52F04 -#include #include #include #if !defined(INT_CONV_WITHOUT_HELPERS) @@ -36,7 +35,7 @@ namespace dhandy { public: constexpr static const std::size_t capacity = S; - using iterator = typename std::array::iterator; + using iterator = T*; constexpr ReversedSizedArray() = default; ~ReversedSizedArray() = default; @@ -45,11 +44,11 @@ namespace dhandy { constexpr const T operator[] (std::size_t idx) const { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; } constexpr T& operator[] (std::size_t idx) { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; } constexpr void push_front (const T& itm) { if (size() == S) throw std::length_error("ReversedSizedArray is full"); m_data[m_curr--] = itm; } - constexpr const T* data() const { return m_data.data() + m_curr + 1; } - constexpr const T* base_ptr() const { return m_data.data(); } - constexpr iterator begin() { return m_data.begin() + m_curr + 1; } - constexpr iterator end() { return m_data.end(); } - constexpr const T& back() const { return *(m_data.data() + S - 1); } + constexpr const T* data() const { return m_data + m_curr + 1; } + constexpr const T* base_ptr() const { return m_data; } + constexpr iterator begin() { return m_data + m_curr + 1; } + constexpr iterator end() { return m_data + S; } + constexpr const T& back() const { return *(m_data + S - 1); } template constexpr V to() const { return V(data(), size() - (not empty() and not back() ? 1 : 0)); } @@ -68,13 +67,13 @@ namespace dhandy { #endif private: - std::array m_data {}; + T m_data[S]; std::size_t m_curr {S - 1}; }; namespace implem { template - constexpr auto elements_or_empty_to_tuple (const std::array& elems, std::size_t from_idx, std::index_sequence) { + constexpr auto elements_or_empty_to_tuple (const T (&elems)[S], std::size_t from_idx, std::index_sequence) { return std::make_tuple((from_idx + Indices < S ? elems[from_idx + Indices] : T{})...); } } //namespace implem From 18cdd4d9b50e82941afa1f9af0eb014dc3bdb497 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 18:58:28 +0200 Subject: [PATCH 46/60] Trying with a smaller lookup, still slower than std::to_string --- include/duckhandy/implem/int_conv.hpp | 35 +++++++++++++-------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index ca59424..ded9174 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -155,22 +155,18 @@ namespace dhandy { template struct IntConversion::value and not std::is_same::value>::type> { - private: - static const constexpr char lookup[200] = { - 0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,1,0,1,1,1,2,1,3,1,4, - 1,5,1,6,1,7,1,8,1,9,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9, - 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,4,0,4,1,4,2,4,3,4,4, - 4,5,4,6,4,7,4,8,4,9,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9, - 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,7,0,7,1,7,2,7,3,7,4, - 7,5,7,6,7,7,7,8,7,9,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9, - 9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9 - }; - - public: static constexpr RevArray to_ary (I in) { using RetType = RevArray; using Num = implem::NumberAdaptation; + //How to build this lookup: 1) write numbers 0, 10, 20..., 90 + //in binary; 2) take the lowest 5 bits, div by 2 and write as + //decimal; 3) divide by 2; 4) the result is the position in the + //below array that should be filled in with the leading digit + //from the original 0-90 number + constexpr const char lookup[16] = { + 0, 0, 0, 7, 4, 1, 0, 0, 8, 5, 2, 0, 0, 9, 6, 3 + }; const bool was_negative = implem::is_negative(in); RetType arr; @@ -179,18 +175,21 @@ namespace dhandy { arr.push_front(Tr::NullChar); in = Num::abs(in); while (in >= static_cast(100)) { - const auto index = (in % 100) * 2; - arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); - arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); + const auto last_two = in % 100; + const auto digit_low = in % 10; in = static_cast(in / static_cast(100)); + const auto digit_high = lookup[((last_two - digit_low) >> 1) & 0xF]; + arr.push_front(Tr::to_digit(static_cast(digit_low))); + arr.push_front(Tr::to_digit(static_cast(digit_high))); }; if (in < static_cast(10)) { arr.push_front(Tr::to_digit(static_cast(in))); } else { - const auto index = in * 2; - arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); - arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); + const auto digit_low = in % 10; + const auto digit_high = lookup[((in - digit_low) >> 1) & 0xF]; + arr.push_front(Tr::to_digit(static_cast(digit_low))); + arr.push_front(Tr::to_digit(static_cast(digit_high))); } if (was_negative) arr.push_front(Tr::Minus); From e1599820b4a49a0c22543898f29155b92ec23618 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 22:13:50 +0200 Subject: [PATCH 47/60] Revert "Trying with a smaller lookup, still slower than std::to_string" This reverts commit 18cdd4d9b50e82941afa1f9af0eb014dc3bdb497. --- include/duckhandy/implem/int_conv.hpp | 35 ++++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index ded9174..ca59424 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -155,18 +155,22 @@ namespace dhandy { template struct IntConversion::value and not std::is_same::value>::type> { + private: + static const constexpr char lookup[200] = { + 0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,1,0,1,1,1,2,1,3,1,4, + 1,5,1,6,1,7,1,8,1,9,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9, + 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,4,0,4,1,4,2,4,3,4,4, + 4,5,4,6,4,7,4,8,4,9,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9, + 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,7,0,7,1,7,2,7,3,7,4, + 7,5,7,6,7,7,7,8,7,9,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9, + 9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9 + }; + + public: static constexpr RevArray to_ary (I in) { using RetType = RevArray; using Num = implem::NumberAdaptation; - //How to build this lookup: 1) write numbers 0, 10, 20..., 90 - //in binary; 2) take the lowest 5 bits, div by 2 and write as - //decimal; 3) divide by 2; 4) the result is the position in the - //below array that should be filled in with the leading digit - //from the original 0-90 number - constexpr const char lookup[16] = { - 0, 0, 0, 7, 4, 1, 0, 0, 8, 5, 2, 0, 0, 9, 6, 3 - }; const bool was_negative = implem::is_negative(in); RetType arr; @@ -175,21 +179,18 @@ namespace dhandy { arr.push_front(Tr::NullChar); in = Num::abs(in); while (in >= static_cast(100)) { - const auto last_two = in % 100; - const auto digit_low = in % 10; + const auto index = (in % 100) * 2; + arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); + arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); in = static_cast(in / static_cast(100)); - const auto digit_high = lookup[((last_two - digit_low) >> 1) & 0xF]; - arr.push_front(Tr::to_digit(static_cast(digit_low))); - arr.push_front(Tr::to_digit(static_cast(digit_high))); }; if (in < static_cast(10)) { arr.push_front(Tr::to_digit(static_cast(in))); } else { - const auto digit_low = in % 10; - const auto digit_high = lookup[((in - digit_low) >> 1) & 0xF]; - arr.push_front(Tr::to_digit(static_cast(digit_low))); - arr.push_front(Tr::to_digit(static_cast(digit_high))); + const auto index = in * 2; + arr.push_front(Tr::to_digit(static_cast(lookup[index + 1]))); + arr.push_front(Tr::to_digit(static_cast(lookup[index + 0]))); } if (was_negative) arr.push_front(Tr::Minus); From 9919f1aeb2861fc74d9ee4aed50a3f1646a4b626 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 7 Jun 2021 23:10:35 +0200 Subject: [PATCH 48/60] Use std::to_string when doing ascii conversions It's fast, it works, it's correct. No need for any of the fancy stuff when all we want is int to ascii string. Currently on my system the implementation of std::to_string is *very* similar to mine, but it doesn't have the overhead of calculating ASCII offsets because their lookup already contains ASCII values. --- include/duckhandy/int_conv.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index 69fa51c..34bd733 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -24,6 +24,8 @@ #include #include +#define DHANDY_INTCONV_USE_STDSTRING + namespace dhandy { namespace implem { template > @@ -42,6 +44,14 @@ namespace dhandy { return IntConvString{retval.begin(), retval.end() - 1}; } }; +#if defined(DHANDY_INTCONV_USE_STDSTRING) + template + struct IntConv>, F, ASCIITranslator, true> { + static IntConvString> conv (const F& in) { + return std::to_string(in); + } + }; +#endif template struct IntConv, F, Tr, true> { consteval static IntConvStringView conv (const F& in) { From 82b520085730af1ba0476cf11378c8d2d1c6de7f Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Tue, 7 Jun 2022 16:41:49 +0200 Subject: [PATCH 49/60] Add meson build scripts --- .gitmodules | 2 +- include/meson.build | 32 + meson.build | 22 + meson_options.txt | 1 + {lib => subprojects/Catch2}/Catch2 | 0 subprojects/Catch2/meson.build | 11 + subprojects/packagefiles/sprout/meson.build | 2694 +++++++++++++++++++ subprojects/sprout.wrap | 7 + test/meson.build | 1 + test/unit/CMakeLists.txt | 2 +- test/unit/meson.build | 19 + 11 files changed, 2789 insertions(+), 2 deletions(-) create mode 100644 include/meson.build create mode 100644 meson.build create mode 100644 meson_options.txt rename {lib => subprojects/Catch2}/Catch2 (100%) create mode 100644 subprojects/Catch2/meson.build create mode 100644 subprojects/packagefiles/sprout/meson.build create mode 100644 subprojects/sprout.wrap create mode 100644 test/meson.build create mode 100644 test/unit/meson.build diff --git a/.gitmodules b/.gitmodules index d49fb06..a4caa47 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "lib/Catch2"] - path = lib/Catch2 + path = subprojects/Catch2/Catch2 url = https://github.com/catchorg/Catch2.git diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 0000000..62a4985 --- /dev/null +++ b/include/meson.build @@ -0,0 +1,32 @@ +if not meson.is_subproject() and meson.version().version_compare('>=0.63.0') + install_headers( + 'duckhandy/implem/IteratorOnPtr.hpp', + 'duckhandy/implem/AutomemBase.hpp', + 'duckhandy/implem/AutomemBase.inl', + 'duckhandy/implem/int_conv.hpp', + 'duckhandy/implem/reversed_sized_array_bt.hpp', + 'duckhandy/version_bt.hpp', + 'duckhandy/has_method.hpp', + 'duckhandy/MaxSizedArray.hpp', + 'duckhandy/MaxSizedArray.inl', + 'duckhandy/bitfield_pack.hpp', + 'duckhandy/cmake_on_off.h', + 'duckhandy/compatibility.h', + 'duckhandy/ducktypes.hpp', + 'duckhandy/endianness.hpp', + 'duckhandy/tiger_bt.hpp', + 'duckhandy/infix_iterator.hpp', + 'duckhandy/int_conv.hpp', + 'duckhandy/int_types.hpp', + 'duckhandy/lengthof.h', + 'duckhandy/nomove_storage.hpp', + 'duckhandy/resource_pool.hpp', + 'duckhandy/tiger_bt.inl', + 'duckhandy/string.hpp', + 'duckhandy/string_bt.hpp', + 'duckhandy/string_view.hpp', + 'duckhandy/stringize.h', + 'duckhandy/variadic_repeat_bt.hpp', + preserve_path: true, #meson v0.63.0 + ) +endif diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..ec90d25 --- /dev/null +++ b/meson.build @@ -0,0 +1,22 @@ +project('duckhandy', + version: '0.1.0', + meson_version: '>=0.56.0', + default_options: ['buildtype=release', 'cpp_std=gnu++20', 'b_ndebug=if-release'] +) + +sprout_dep = dependency('sprout', allow_fallback: true) + +public_incl = include_directories('include') + +duckhandy_dep = declare_dependency( + include_directories: [ + public_incl, + ], + dependencies: [sprout_dep], +) + +if get_option('build_testing') + subdir('test') +endif + +subdir('include') diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..b6219ff --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('build_testing', type: 'boolean', value: true) diff --git a/lib/Catch2 b/subprojects/Catch2/Catch2 similarity index 100% rename from lib/Catch2 rename to subprojects/Catch2/Catch2 diff --git a/subprojects/Catch2/meson.build b/subprojects/Catch2/meson.build new file mode 100644 index 0000000..0eb0ce2 --- /dev/null +++ b/subprojects/Catch2/meson.build @@ -0,0 +1,11 @@ +project('Catch2', + version: '2.13.6', + meson_version: '>=0.54.0', +) + +public_incl = include_directories('Catch2/single_include') +catch2_dep = declare_dependency( + include_directories: public_incl +) + +meson.override_dependency(meson.project_name(), catch2_dep) diff --git a/subprojects/packagefiles/sprout/meson.build b/subprojects/packagefiles/sprout/meson.build new file mode 100644 index 0000000..96781e4 --- /dev/null +++ b/subprojects/packagefiles/sprout/meson.build @@ -0,0 +1,2694 @@ +project('sprout', 'cpp', + meson_version: '>=0.56.0', + version: '20190615', +) + +public_incl = include_directories('.') +sprout_dep = declare_dependency( + include_directories: public_incl, +) + +meson.override_dependency(meson.project_name(), sprout_dep) + +if not meson.is_subproject() and meson.version().version_compare('>=0.63.0') + install_headers( + 'sprout/adapt/boost/array.hpp', + 'sprout/adapt/sscrisk/cel/array.hpp', + 'sprout/adapt/sscrisk/cel/utility.hpp', + 'sprout/adapt/std/array.hpp', + 'sprout/adapt/std/complex.hpp', + 'sprout/adapt/std/utility.hpp', + 'sprout/adl/not_found.hpp', + 'sprout/algorithm.hpp', + 'sprout/algorithm/abs_diff.hpp', + 'sprout/algorithm/adjacent_find.hpp', + 'sprout/algorithm/all_of.hpp', + 'sprout/algorithm/all_of_equal.hpp', + 'sprout/algorithm/any_of.hpp', + 'sprout/algorithm/any_of_equal.hpp', + 'sprout/algorithm/binary_search.hpp', + 'sprout/algorithm/bogo_sort.hpp', + 'sprout/algorithm/bogo_sort_result.hpp', + 'sprout/algorithm/bozo_sort.hpp', + 'sprout/algorithm/bozo_sort_result.hpp', + 'sprout/algorithm/clamp.hpp', + 'sprout/algorithm/clamp_range.hpp', + 'sprout/algorithm/clamp_range_copy.hpp', + 'sprout/algorithm/copy.hpp', + 'sprout/algorithm/copy_backward.hpp', + 'sprout/algorithm/copy_if.hpp', + 'sprout/algorithm/copy_n.hpp', + 'sprout/algorithm/copy_until.hpp', + 'sprout/algorithm/copy_while.hpp', + 'sprout/algorithm/count.hpp', + 'sprout/algorithm/count_if.hpp', + 'sprout/algorithm/cxx14.hpp', + 'sprout/algorithm/cxx14/bogo_sort.hpp', + 'sprout/algorithm/cxx14/bozo_sort.hpp', + 'sprout/algorithm/cxx14/clamp_range.hpp', + 'sprout/algorithm/cxx14/copy.hpp', + 'sprout/algorithm/cxx14/copy_backward.hpp', + 'sprout/algorithm/cxx14/copy_if.hpp', + 'sprout/algorithm/cxx14/copy_n.hpp', + 'sprout/algorithm/cxx14/copy_until.hpp', + 'sprout/algorithm/cxx14/copy_while.hpp', + 'sprout/algorithm/cxx14/detail/heap_tool.hpp', + 'sprout/algorithm/cxx14/detail/insertion_sort.hpp', + 'sprout/algorithm/cxx14/detail/sort_tool.hpp', + 'sprout/algorithm/cxx14/fill.hpp', + 'sprout/algorithm/cxx14/fill_n.hpp', + 'sprout/algorithm/cxx14/for_each.hpp', + 'sprout/algorithm/cxx14/for_each_n.hpp', + 'sprout/algorithm/cxx14/gather.hpp', + 'sprout/algorithm/cxx14/generate.hpp', + 'sprout/algorithm/cxx14/generate_n.hpp', + 'sprout/algorithm/cxx14/inplace_merge.hpp', + 'sprout/algorithm/cxx14/iter_swap.hpp', + 'sprout/algorithm/cxx14/make_heap.hpp', + 'sprout/algorithm/cxx14/merge.hpp', + 'sprout/algorithm/cxx14/move.hpp', + 'sprout/algorithm/cxx14/move_backward.hpp', + 'sprout/algorithm/cxx14/next_permutation.hpp', + 'sprout/algorithm/cxx14/nth_element.hpp', + 'sprout/algorithm/cxx14/partial_sort.hpp', + 'sprout/algorithm/cxx14/partial_sort_copy.hpp', + 'sprout/algorithm/cxx14/partition.hpp', + 'sprout/algorithm/cxx14/partition_copy.hpp', + 'sprout/algorithm/cxx14/pop_heap.hpp', + 'sprout/algorithm/cxx14/prev_permutation.hpp', + 'sprout/algorithm/cxx14/push_heap.hpp', + 'sprout/algorithm/cxx14/random_shuffle.hpp', + 'sprout/algorithm/cxx14/random_swap.hpp', + 'sprout/algorithm/cxx14/remove.hpp', + 'sprout/algorithm/cxx14/remove_copy.hpp', + 'sprout/algorithm/cxx14/remove_copy_if.hpp', + 'sprout/algorithm/cxx14/remove_if.hpp', + 'sprout/algorithm/cxx14/replace.hpp', + 'sprout/algorithm/cxx14/replace_copy.hpp', + 'sprout/algorithm/cxx14/replace_copy_if.hpp', + 'sprout/algorithm/cxx14/replace_if.hpp', + 'sprout/algorithm/cxx14/reverse.hpp', + 'sprout/algorithm/cxx14/reverse_copy.hpp', + 'sprout/algorithm/cxx14/rotate.hpp', + 'sprout/algorithm/cxx14/rotate_copy.hpp', + 'sprout/algorithm/cxx14/sample.hpp', + 'sprout/algorithm/cxx14/set_difference.hpp', + 'sprout/algorithm/cxx14/set_intersection.hpp', + 'sprout/algorithm/cxx14/set_symmetric_difference.hpp', + 'sprout/algorithm/cxx14/set_union.hpp', + 'sprout/algorithm/cxx14/shuffle.hpp', + 'sprout/algorithm/cxx14/sort.hpp', + 'sprout/algorithm/cxx14/sort_heap.hpp', + 'sprout/algorithm/cxx14/stable_partition.hpp', + 'sprout/algorithm/cxx14/stable_sort.hpp', + 'sprout/algorithm/cxx14/swap_ranges.hpp', + 'sprout/algorithm/cxx14/transform.hpp', + 'sprout/algorithm/cxx14/unique.hpp', + 'sprout/algorithm/cxx14/unique_copy.hpp', + 'sprout/algorithm/detail/max.hpp', + 'sprout/algorithm/detail/min.hpp', + 'sprout/algorithm/equal.hpp', + 'sprout/algorithm/equal_range.hpp', + 'sprout/algorithm/fill.hpp', + 'sprout/algorithm/fill_n.hpp', + 'sprout/algorithm/find.hpp', + 'sprout/algorithm/find_difference.hpp', + 'sprout/algorithm/find_end.hpp', + 'sprout/algorithm/find_first_of.hpp', + 'sprout/algorithm/find_if.hpp', + 'sprout/algorithm/find_if_not.hpp', + 'sprout/algorithm/find_intersection.hpp', + 'sprout/algorithm/find_symmetric_difference.hpp', + 'sprout/algorithm/fit.hpp', + 'sprout/algorithm/fit/bogo_sort.hpp', + 'sprout/algorithm/fit/bogo_sort_result.hpp', + 'sprout/algorithm/fit/bozo_sort.hpp', + 'sprout/algorithm/fit/bozo_sort_result.hpp', + 'sprout/algorithm/fit/clamp_range.hpp', + 'sprout/algorithm/fit/clamp_range_copy.hpp', + 'sprout/algorithm/fit/copy.hpp', + 'sprout/algorithm/fit/copy_backward.hpp', + 'sprout/algorithm/fit/copy_if.hpp', + 'sprout/algorithm/fit/copy_n.hpp', + 'sprout/algorithm/fit/copy_until.hpp', + 'sprout/algorithm/fit/copy_while.hpp', + 'sprout/algorithm/fit/fill.hpp', + 'sprout/algorithm/fit/fill_n.hpp', + 'sprout/algorithm/fit/generate.hpp', + 'sprout/algorithm/fit/generate_n.hpp', + 'sprout/algorithm/fit/inplace_merge.hpp', + 'sprout/algorithm/fit/make_heap.hpp', + 'sprout/algorithm/fit/make_partial_heap.hpp', + 'sprout/algorithm/fit/merge.hpp', + 'sprout/algorithm/fit/next_permutation.hpp', + 'sprout/algorithm/fit/nth_element.hpp', + 'sprout/algorithm/fit/partial_sort.hpp', + 'sprout/algorithm/fit/partition.hpp', + 'sprout/algorithm/fit/partition_copy.hpp', + 'sprout/algorithm/fit/pop_heap.hpp', + 'sprout/algorithm/fit/prev_permutation.hpp', + 'sprout/algorithm/fit/push_heap.hpp', + 'sprout/algorithm/fit/random_swap.hpp', + 'sprout/algorithm/fit/random_swap_result.hpp', + 'sprout/algorithm/fit/recurrence.hpp', + 'sprout/algorithm/fit/recurrence_n.hpp', + 'sprout/algorithm/fit/remove.hpp', + 'sprout/algorithm/fit/remove_copy.hpp', + 'sprout/algorithm/fit/remove_copy_if.hpp', + 'sprout/algorithm/fit/remove_if.hpp', + 'sprout/algorithm/fit/replace.hpp', + 'sprout/algorithm/fit/replace_copy.hpp', + 'sprout/algorithm/fit/replace_copy_if.hpp', + 'sprout/algorithm/fit/replace_if.hpp', + 'sprout/algorithm/fit/results.hpp', + 'sprout/algorithm/fit/reverse.hpp', + 'sprout/algorithm/fit/reverse_copy.hpp', + 'sprout/algorithm/fit/rotate.hpp', + 'sprout/algorithm/fit/rotate_copy.hpp', + 'sprout/algorithm/fit/set_difference.hpp', + 'sprout/algorithm/fit/set_intersection.hpp', + 'sprout/algorithm/fit/set_symmetric_difference.hpp', + 'sprout/algorithm/fit/set_union.hpp', + 'sprout/algorithm/fit/shuffle.hpp', + 'sprout/algorithm/fit/shuffle_result.hpp', + 'sprout/algorithm/fit/sort.hpp', + 'sprout/algorithm/fit/sort_heap.hpp', + 'sprout/algorithm/fit/stable_partition.hpp', + 'sprout/algorithm/fit/stable_partition_copy.hpp', + 'sprout/algorithm/fit/stable_sort.hpp', + 'sprout/algorithm/fit/swap_element.hpp', + 'sprout/algorithm/fit/swap_element_copy.hpp', + 'sprout/algorithm/fit/transform.hpp', + 'sprout/algorithm/fit/unfold.hpp', + 'sprout/algorithm/fit/unfold_n.hpp', + 'sprout/algorithm/fit/unique.hpp', + 'sprout/algorithm/fit/unique_copy.hpp', + 'sprout/algorithm/fixed.hpp', + 'sprout/algorithm/fixed/bogo_sort.hpp', + 'sprout/algorithm/fixed/bogo_sort_result.hpp', + 'sprout/algorithm/fixed/bozo_sort.hpp', + 'sprout/algorithm/fixed/bozo_sort_result.hpp', + 'sprout/algorithm/fixed/clamp_range.hpp', + 'sprout/algorithm/fixed/clamp_range_copy.hpp', + 'sprout/algorithm/fixed/copy.hpp', + 'sprout/algorithm/fixed/copy_backward.hpp', + 'sprout/algorithm/fixed/copy_if.hpp', + 'sprout/algorithm/fixed/copy_n.hpp', + 'sprout/algorithm/fixed/copy_until.hpp', + 'sprout/algorithm/fixed/copy_while.hpp', + 'sprout/algorithm/fixed/deprecated/sort.hpp', + 'sprout/algorithm/fixed/fill.hpp', + 'sprout/algorithm/fixed/fill_n.hpp', + 'sprout/algorithm/fixed/generate.hpp', + 'sprout/algorithm/fixed/generate_n.hpp', + 'sprout/algorithm/fixed/inplace_merge.hpp', + 'sprout/algorithm/fixed/make_heap.hpp', + 'sprout/algorithm/fixed/make_partial_heap.hpp', + 'sprout/algorithm/fixed/merge.hpp', + 'sprout/algorithm/fixed/next_permutation.hpp', + 'sprout/algorithm/fixed/nth_element.hpp', + 'sprout/algorithm/fixed/partial_sort.hpp', + 'sprout/algorithm/fixed/partition.hpp', + 'sprout/algorithm/fixed/partition_copy.hpp', + 'sprout/algorithm/fixed/pop_heap.hpp', + 'sprout/algorithm/fixed/prev_permutation.hpp', + 'sprout/algorithm/fixed/push_heap.hpp', + 'sprout/algorithm/fixed/random_swap.hpp', + 'sprout/algorithm/fixed/random_swap_result.hpp', + 'sprout/algorithm/fixed/recurrence.hpp', + 'sprout/algorithm/fixed/recurrence_n.hpp', + 'sprout/algorithm/fixed/remove.hpp', + 'sprout/algorithm/fixed/remove_copy.hpp', + 'sprout/algorithm/fixed/remove_copy_if.hpp', + 'sprout/algorithm/fixed/remove_if.hpp', + 'sprout/algorithm/fixed/replace.hpp', + 'sprout/algorithm/fixed/replace_copy.hpp', + 'sprout/algorithm/fixed/replace_copy_if.hpp', + 'sprout/algorithm/fixed/replace_if.hpp', + 'sprout/algorithm/fixed/results.hpp', + 'sprout/algorithm/fixed/reverse.hpp', + 'sprout/algorithm/fixed/reverse_copy.hpp', + 'sprout/algorithm/fixed/rotate.hpp', + 'sprout/algorithm/fixed/rotate_copy.hpp', + 'sprout/algorithm/fixed/set_difference.hpp', + 'sprout/algorithm/fixed/set_intersection.hpp', + 'sprout/algorithm/fixed/set_symmetric_difference.hpp', + 'sprout/algorithm/fixed/set_union.hpp', + 'sprout/algorithm/fixed/shuffle.hpp', + 'sprout/algorithm/fixed/shuffle_result.hpp', + 'sprout/algorithm/fixed/sort.hpp', + 'sprout/algorithm/fixed/sort_heap.hpp', + 'sprout/algorithm/fixed/stable_partition.hpp', + 'sprout/algorithm/fixed/stable_partition_copy.hpp', + 'sprout/algorithm/fixed/stable_sort.hpp', + 'sprout/algorithm/fixed/swap_element.hpp', + 'sprout/algorithm/fixed/swap_element_copy.hpp', + 'sprout/algorithm/fixed/transform.hpp', + 'sprout/algorithm/fixed/unfold.hpp', + 'sprout/algorithm/fixed/unfold_n.hpp', + 'sprout/algorithm/fixed/unique.hpp', + 'sprout/algorithm/fixed/unique_copy.hpp', + 'sprout/algorithm/fold_until.hpp', + 'sprout/algorithm/fold_while.hpp', + 'sprout/algorithm/for_each.hpp', + 'sprout/algorithm/for_each_n.hpp', + 'sprout/algorithm/gather.hpp', + 'sprout/algorithm/generate.hpp', + 'sprout/algorithm/generate_n.hpp', + 'sprout/algorithm/includes.hpp', + 'sprout/algorithm/inplace_merge.hpp', + 'sprout/algorithm/is_decreasing.hpp', + 'sprout/algorithm/is_heap.hpp', + 'sprout/algorithm/is_heap_until.hpp', + 'sprout/algorithm/is_increasing.hpp', + 'sprout/algorithm/is_partitioned.hpp', + 'sprout/algorithm/is_permutation.hpp', + 'sprout/algorithm/is_sorted.hpp', + 'sprout/algorithm/is_sorted_until.hpp', + 'sprout/algorithm/is_strictly_decreasing.hpp', + 'sprout/algorithm/is_strictly_increasing.hpp', + 'sprout/algorithm/iter_swap.hpp', + 'sprout/algorithm/lexicographical_compare.hpp', + 'sprout/algorithm/lower_bound.hpp', + 'sprout/algorithm/make_heap.hpp', + 'sprout/algorithm/make_partial_heap.hpp', + 'sprout/algorithm/max.hpp', + 'sprout/algorithm/max_element.hpp', + 'sprout/algorithm/merge.hpp', + 'sprout/algorithm/min.hpp', + 'sprout/algorithm/min_element.hpp', + 'sprout/algorithm/minmax.hpp', + 'sprout/algorithm/minmax_element.hpp', + 'sprout/algorithm/mismatch.hpp', + 'sprout/algorithm/modifying.hpp', + 'sprout/algorithm/move.hpp', + 'sprout/algorithm/move_backward.hpp', + 'sprout/algorithm/next_difference.hpp', + 'sprout/algorithm/next_intersection.hpp', + 'sprout/algorithm/next_permutation.hpp', + 'sprout/algorithm/next_symmetric_difference.hpp', + 'sprout/algorithm/next_union.hpp', + 'sprout/algorithm/non_modifying.hpp', + 'sprout/algorithm/none_of.hpp', + 'sprout/algorithm/none_of_equal.hpp', + 'sprout/algorithm/nth_element.hpp', + 'sprout/algorithm/one_of.hpp', + 'sprout/algorithm/one_of_equal.hpp', + 'sprout/algorithm/partial_sort.hpp', + 'sprout/algorithm/partial_sort_copy.hpp', + 'sprout/algorithm/partition.hpp', + 'sprout/algorithm/partition_copy.hpp', + 'sprout/algorithm/partition_point.hpp', + 'sprout/algorithm/pop_heap.hpp', + 'sprout/algorithm/prev_permutation.hpp', + 'sprout/algorithm/push_heap.hpp', + 'sprout/algorithm/random_shuffle.hpp', + 'sprout/algorithm/random_swap.hpp', + 'sprout/algorithm/random_swap_result.hpp', + 'sprout/algorithm/recurrence.hpp', + 'sprout/algorithm/recurrence_n.hpp', + 'sprout/algorithm/remove.hpp', + 'sprout/algorithm/remove_copy.hpp', + 'sprout/algorithm/remove_copy_if.hpp', + 'sprout/algorithm/remove_if.hpp', + 'sprout/algorithm/replace.hpp', + 'sprout/algorithm/replace_copy.hpp', + 'sprout/algorithm/replace_copy_if.hpp', + 'sprout/algorithm/replace_if.hpp', + 'sprout/algorithm/reverse.hpp', + 'sprout/algorithm/reverse_copy.hpp', + 'sprout/algorithm/rotate.hpp', + 'sprout/algorithm/rotate_copy.hpp', + 'sprout/algorithm/sample.hpp', + 'sprout/algorithm/search.hpp', + 'sprout/algorithm/search_n.hpp', + 'sprout/algorithm/searching.hpp', + 'sprout/algorithm/searching/default_searcher.hpp', + 'sprout/algorithm/set_difference.hpp', + 'sprout/algorithm/set_intersection.hpp', + 'sprout/algorithm/set_symmetric_difference.hpp', + 'sprout/algorithm/set_union.hpp', + 'sprout/algorithm/shuffle.hpp', + 'sprout/algorithm/shuffle_result.hpp', + 'sprout/algorithm/sort.hpp', + 'sprout/algorithm/sort_heap.hpp', + 'sprout/algorithm/stable_partition.hpp', + 'sprout/algorithm/stable_partition_copy.hpp', + 'sprout/algorithm/stable_sort.hpp', + 'sprout/algorithm/string.hpp', + 'sprout/algorithm/string/case_conv.hpp', + 'sprout/algorithm/string/fit/case_conv.hpp', + 'sprout/algorithm/string/fit/to_lower.hpp', + 'sprout/algorithm/string/fit/to_lower_copy.hpp', + 'sprout/algorithm/string/fit/to_upper.hpp', + 'sprout/algorithm/string/fit/to_upper_copy.hpp', + 'sprout/algorithm/string/fixed/case_conv.hpp', + 'sprout/algorithm/string/fixed/to_lower.hpp', + 'sprout/algorithm/string/fixed/to_lower_copy.hpp', + 'sprout/algorithm/string/fixed/to_upper.hpp', + 'sprout/algorithm/string/fixed/to_upper_copy.hpp', + 'sprout/algorithm/string/join.hpp', + 'sprout/algorithm/string/to_lower.hpp', + 'sprout/algorithm/string/to_lower_copy.hpp', + 'sprout/algorithm/string/to_upper.hpp', + 'sprout/algorithm/string/to_upper_copy.hpp', + 'sprout/algorithm/swap_element.hpp', + 'sprout/algorithm/swap_element_copy.hpp', + 'sprout/algorithm/swap_ranges.hpp', + 'sprout/algorithm/transform.hpp', + 'sprout/algorithm/tristate_lexicographical_compare.hpp', + 'sprout/algorithm/unfold.hpp', + 'sprout/algorithm/unfold_n.hpp', + 'sprout/algorithm/unique.hpp', + 'sprout/algorithm/unique_copy.hpp', + 'sprout/algorithm/upper_bound.hpp', + 'sprout/array.hpp', + 'sprout/array/array.hpp', + 'sprout/array/comparison.hpp', + 'sprout/array/hash.hpp', + 'sprout/array/make_array.hpp', + 'sprout/array/nested_array.hpp', + 'sprout/array/tuple.hpp', + 'sprout/array/type_traits.hpp', + 'sprout/assert.hpp', + 'sprout/bit/bit_length.hpp', + 'sprout/bit/bit_reverse.hpp', + 'sprout/bit/clrsb.hpp', + 'sprout/bit/clz.hpp', + 'sprout/bit/cntl0.hpp', + 'sprout/bit/cntl1.hpp', + 'sprout/bit/cntt0.hpp', + 'sprout/bit/cntt1.hpp', + 'sprout/bit/count.hpp', + 'sprout/bit/ctz.hpp', + 'sprout/bit/flipbit.hpp', + 'sprout/bit/flipbitsge.hpp', + 'sprout/bit/flipbitsle.hpp', + 'sprout/bit/isols0b.hpp', + 'sprout/bit/isols1b.hpp', + 'sprout/bit/length.hpp', + 'sprout/bit/maskt0.hpp', + 'sprout/bit/maskt0ls1b.hpp', + 'sprout/bit/maskt1.hpp', + 'sprout/bit/maskt1ls0b.hpp', + 'sprout/bit/operation.hpp', + 'sprout/bit/parity.hpp', + 'sprout/bit/popcount.hpp', + 'sprout/bit/range.hpp', + 'sprout/bit/reverse.hpp', + 'sprout/bit/rightmost.hpp', + 'sprout/bit/rotl.hpp', + 'sprout/bit/rotr.hpp', + 'sprout/bit/rstbit.hpp', + 'sprout/bit/rstbitsge.hpp', + 'sprout/bit/rstbitsle.hpp', + 'sprout/bit/rstls1b.hpp', + 'sprout/bit/rstt1.hpp', + 'sprout/bit/setbit.hpp', + 'sprout/bit/setbitsge.hpp', + 'sprout/bit/setbitsle.hpp', + 'sprout/bit/setls0b.hpp', + 'sprout/bit/sett0.hpp', + 'sprout/bit/shal.hpp', + 'sprout/bit/shar.hpp', + 'sprout/bit/shift.hpp', + 'sprout/bit/shll.hpp', + 'sprout/bit/shlr.hpp', + 'sprout/bit/single.hpp', + 'sprout/bit/testbit.hpp', + 'sprout/bitset.hpp', + 'sprout/bitset/bitset.hpp', + 'sprout/bitset/bitwise.hpp', + 'sprout/bitset/hash.hpp', + 'sprout/bitset/io.hpp', + 'sprout/brainfuck.hpp', + 'sprout/brainfuck/brainfuck.hpp', + 'sprout/brainfuck/detail/convert.hpp', + 'sprout/brainfuck/misa.hpp', + 'sprout/brainfuck/ook.hpp', + 'sprout/cctype.hpp', + 'sprout/checksum.hpp', + 'sprout/checksum/md5.hpp', + 'sprout/checksum/sha1.hpp', + 'sprout/checksum/sum.hpp', + 'sprout/checksum/xor.hpp', + 'sprout/cinttypes.hpp', + 'sprout/cinttypes/abs.hpp', + 'sprout/cinttypes/arithmetic.hpp', + 'sprout/cinttypes/conversion.hpp', + 'sprout/cinttypes/div.hpp', + 'sprout/cinttypes/strtoimax.hpp', + 'sprout/cinttypes/strtoumax.hpp', + 'sprout/cmath.hpp', + 'sprout/complex.hpp', + 'sprout/complex/abs.hpp', + 'sprout/complex/acos.hpp', + 'sprout/complex/acosh.hpp', + 'sprout/complex/arg.hpp', + 'sprout/complex/arithmetic_operators.hpp', + 'sprout/complex/asin.hpp', + 'sprout/complex/asinh.hpp', + 'sprout/complex/atan.hpp', + 'sprout/complex/atanh.hpp', + 'sprout/complex/complex.hpp', + 'sprout/complex/conj.hpp', + 'sprout/complex/container.hpp', + 'sprout/complex/cos.hpp', + 'sprout/complex/cosh.hpp', + 'sprout/complex/detail/copysign_mul.hpp', + 'sprout/complex/euler.hpp', + 'sprout/complex/exp.hpp', + 'sprout/complex/hash.hpp', + 'sprout/complex/imag.hpp', + 'sprout/complex/literals.hpp', + 'sprout/complex/log.hpp', + 'sprout/complex/log10.hpp', + 'sprout/complex/log2.hpp', + 'sprout/complex/nearest.hpp', + 'sprout/complex/norm.hpp', + 'sprout/complex/operators.hpp', + 'sprout/complex/perp.hpp', + 'sprout/complex/polar.hpp', + 'sprout/complex/pow.hpp', + 'sprout/complex/proj.hpp', + 'sprout/complex/real.hpp', + 'sprout/complex/sin.hpp', + 'sprout/complex/sinh.hpp', + 'sprout/complex/sqrt.hpp', + 'sprout/complex/stream_operators.hpp', + 'sprout/complex/tan.hpp', + 'sprout/complex/tanh.hpp', + 'sprout/complex/transcendentals.hpp', + 'sprout/complex/tuple.hpp', + 'sprout/complex/type_traits.hpp', + 'sprout/complex/values.hpp', + 'sprout/compost.hpp', + 'sprout/compost/analyses.hpp', + 'sprout/compost/analyses/amplitude_spectrum.hpp', + 'sprout/compost/analyses/dft.hpp', + 'sprout/compost/analyses/idft.hpp', + 'sprout/compost/analyses/phase_spectrum.hpp', + 'sprout/compost/effects.hpp', + 'sprout/compost/effects/auto_pan.hpp', + 'sprout/compost/effects/changed_volume.hpp', + 'sprout/compost/effects/chorus.hpp', + 'sprout/compost/effects/clipped.hpp', + 'sprout/compost/effects/compressed.hpp', + 'sprout/compost/effects/distorted.hpp', + 'sprout/compost/effects/fuzzed.hpp', + 'sprout/compost/effects/noise_gated.hpp', + 'sprout/compost/effects/overdriven.hpp', + 'sprout/compost/effects/pseudo_stereo.hpp', + 'sprout/compost/effects/rectified.hpp', + 'sprout/compost/effects/reverbed.hpp', + 'sprout/compost/effects/superposed.hpp', + 'sprout/compost/effects/tremolo.hpp', + 'sprout/compost/effects/vibrato.hpp', + 'sprout/compost/effects/vocal_cancelled.hpp', + 'sprout/compost/formats.hpp', + 'sprout/compost/formats/as_complex.hpp', + 'sprout/compost/formats/as_imag.hpp', + 'sprout/compost/formats/as_pcm_wave.hpp', + 'sprout/compost/formats/as_real.hpp', + 'sprout/compost/formats/effected_each.hpp', + 'sprout/compost/formats/effected_left.hpp', + 'sprout/compost/formats/effected_right.hpp', + 'sprout/compost/formats/left_channel.hpp', + 'sprout/compost/formats/right_channel.hpp', + 'sprout/compost/formats/stereo.hpp', + 'sprout/compost/load/source.hpp', + 'sprout/compost/ranges.hpp', + 'sprout/compost/ranges/adapted_dropped.hpp', + 'sprout/compost/ranges/adapted_dropped_end.hpp', + 'sprout/compost/ranges/adapted_offset.hpp', + 'sprout/compost/ranges/adapted_taken.hpp', + 'sprout/compost/ranges/adapted_taken_end.hpp', + 'sprout/compost/ranges/adapted_window.hpp', + 'sprout/compost/ranges/copied.hpp', + 'sprout/compost/ranges/dropped.hpp', + 'sprout/compost/ranges/dropped_end.hpp', + 'sprout/compost/ranges/jointed.hpp', + 'sprout/compost/ranges/offset.hpp', + 'sprout/compost/ranges/piped.hpp', + 'sprout/compost/ranges/taken.hpp', + 'sprout/compost/ranges/taken_end.hpp', + 'sprout/compost/ranges/window.hpp', + 'sprout/compost/sources.hpp', + 'sprout/compost/sources/source.hpp', + 'sprout/compost/utility.hpp', + 'sprout/compost/utility/equal_temperament.hpp', + 'sprout/compost/utility/iir_filter.hpp', + 'sprout/compost/utility/rosenberg.hpp', + 'sprout/compost/waves.hpp', + 'sprout/compost/waves/blanked.hpp', + 'sprout/compost/waves/sawtooth_wave.hpp', + 'sprout/compost/waves/sinusoidal.hpp', + 'sprout/compost/waves/square_wave.hpp', + 'sprout/compost/waves/triangle_wave.hpp', + 'sprout/compost/waves/white_noise.hpp', + 'sprout/compressed_pair.hpp', + 'sprout/config.hpp', + 'sprout/config/auto_config.hpp', + 'sprout/config/compiler.hpp', + 'sprout/config/compiler/borland.hpp', + 'sprout/config/compiler/clang.hpp', + 'sprout/config/compiler/codegear.hpp', + 'sprout/config/compiler/comeau.hpp', + 'sprout/config/compiler/common_edg.hpp', + 'sprout/config/compiler/compaq_cxx.hpp', + 'sprout/config/compiler/cray.hpp', + 'sprout/config/compiler/digitalmars.hpp', + 'sprout/config/compiler/gcc.hpp', + 'sprout/config/compiler/gcc_xml.hpp', + 'sprout/config/compiler/greenhills.hpp', + 'sprout/config/compiler/has_future.hpp', + 'sprout/config/compiler/hp_acc.hpp', + 'sprout/config/compiler/intel.hpp', + 'sprout/config/compiler/kai.hpp', + 'sprout/config/compiler/metrowerks.hpp', + 'sprout/config/compiler/mpw.hpp', + 'sprout/config/compiler/no_future.hpp', + 'sprout/config/compiler/nvcc.hpp', + 'sprout/config/compiler/pathscale.hpp', + 'sprout/config/compiler/pgi.hpp', + 'sprout/config/compiler/sgi_mipspro.hpp', + 'sprout/config/compiler/sunpro_cc.hpp', + 'sprout/config/compiler/vacpp.hpp', + 'sprout/config/compiler/visualc.hpp', + 'sprout/config/config.hpp', + 'sprout/config/stdlib.hpp', + 'sprout/config/stdlib/dinkumware.hpp', + 'sprout/config/stdlib/libcomo.hpp', + 'sprout/config/stdlib/libcpp.hpp', + 'sprout/config/stdlib/libstdcpp3.hpp', + 'sprout/config/stdlib/modena.hpp', + 'sprout/config/stdlib/msl.hpp', + 'sprout/config/stdlib/roguewave.hpp', + 'sprout/config/stdlib/sgi.hpp', + 'sprout/config/stdlib/stlport.hpp', + 'sprout/config/stdlib/vacpp.hpp', + 'sprout/config/suffix.hpp', + 'sprout/config/user_config.hpp', + 'sprout/container.hpp', + 'sprout/container/at.hpp', + 'sprout/container/back.hpp', + 'sprout/container/begin.hpp', + 'sprout/container/boost/array.hpp', + 'sprout/container/const_iterator.hpp', + 'sprout/container/const_pointer.hpp', + 'sprout/container/const_reference.hpp', + 'sprout/container/construct_functions.hpp', + 'sprout/container/container_construct_traits.hpp', + 'sprout/container/container_fitness_traits.hpp', + 'sprout/container/container_holder.hpp', + 'sprout/container/container_range_traits.hpp', + 'sprout/container/container_traits.hpp', + 'sprout/container/container_transform_traits.hpp', + 'sprout/container/copied_type.hpp', + 'sprout/container/data.hpp', + 'sprout/container/deep_copy.hpp', + 'sprout/container/deep_internal.hpp', + 'sprout/container/detail/array_like.hpp', + 'sprout/container/detail/range_at.hpp', + 'sprout/container/detail/range_back.hpp', + 'sprout/container/detail/range_begin.hpp', + 'sprout/container/detail/range_data.hpp', + 'sprout/container/detail/range_empty.hpp', + 'sprout/container/detail/range_end.hpp', + 'sprout/container/detail/range_front.hpp', + 'sprout/container/detail/range_index_of.hpp', + 'sprout/container/detail/range_nth.hpp', + 'sprout/container/detail/range_size.hpp', + 'sprout/container/detail/range_subscript_at.hpp', + 'sprout/container/difference_type.hpp', + 'sprout/container/empty.hpp', + 'sprout/container/end.hpp', + 'sprout/container/fit_size.hpp', + 'sprout/container/fitness_functions.hpp', + 'sprout/container/fixed_size.hpp', + 'sprout/container/front.hpp', + 'sprout/container/functions.hpp', + 'sprout/container/get_deep_internal.hpp', + 'sprout/container/get_internal.hpp', + 'sprout/container/has_sprout_begin.hpp', + 'sprout/container/has_sprout_end.hpp', + 'sprout/container/index_of.hpp', + 'sprout/container/indexes.hpp', + 'sprout/container/internal.hpp', + 'sprout/container/internal_begin.hpp', + 'sprout/container/internal_begin_offset.hpp', + 'sprout/container/internal_begin_offset_backward.hpp', + 'sprout/container/internal_deep_copy.hpp', + 'sprout/container/internal_end.hpp', + 'sprout/container/internal_end_offset.hpp', + 'sprout/container/internal_end_offset_backward.hpp', + 'sprout/container/internal_size.hpp', + 'sprout/container/is_sub_container.hpp', + 'sprout/container/iterator.hpp', + 'sprout/container/make.hpp', + 'sprout/container/metafunctions.hpp', + 'sprout/container/nth.hpp', + 'sprout/container/pointer.hpp', + 'sprout/container/range_functions.hpp', + 'sprout/container/range_functions_fwd.hpp', + 'sprout/container/range_index_check.hpp', + 'sprout/container/rebind_size.hpp', + 'sprout/container/rebind_type.hpp', + 'sprout/container/reference.hpp', + 'sprout/container/remake.hpp', + 'sprout/container/shrink_to_fit.hpp', + 'sprout/container/size.hpp', + 'sprout/container/size_type.hpp', + 'sprout/container/sscrisk/cel/array.hpp', + 'sprout/container/static_size.hpp', + 'sprout/container/std/array.hpp', + 'sprout/container/std/complex.hpp', + 'sprout/container/sub_container_traits.hpp', + 'sprout/container/sub_functions.hpp', + 'sprout/container/subscript_at.hpp', + 'sprout/container/traits.hpp', + 'sprout/container/traits_functions.hpp', + 'sprout/container/traits_fwd.hpp', + 'sprout/container/utility.hpp', + 'sprout/container/value_type.hpp', + 'sprout/container/weak_rebind_size.hpp', + 'sprout/cstddef.hpp', + 'sprout/cstddef/literals.hpp', + 'sprout/cstdint.hpp', + 'sprout/cstdlib.hpp', + 'sprout/cstdlib/abs.hpp', + 'sprout/cstdlib/arithmetic.hpp', + 'sprout/cstdlib/ascii_to_int.hpp', + 'sprout/cstdlib/atof.hpp', + 'sprout/cstdlib/atoi.hpp', + 'sprout/cstdlib/atol.hpp', + 'sprout/cstdlib/atoll.hpp', + 'sprout/cstdlib/conversion.hpp', + 'sprout/cstdlib/div.hpp', + 'sprout/cstdlib/str_to_float.hpp', + 'sprout/cstdlib/str_to_int.hpp', + 'sprout/cstdlib/strtod.hpp', + 'sprout/cstdlib/strtof.hpp', + 'sprout/cstdlib/strtol.hpp', + 'sprout/cstdlib/strtold.hpp', + 'sprout/cstdlib/strtoll.hpp', + 'sprout/cstdlib/strtoul.hpp', + 'sprout/cstdlib/strtoull.hpp', + 'sprout/cstring.hpp', + 'sprout/cstring/memchr.hpp', + 'sprout/cstring/memcmp.hpp', + 'sprout/cstring/memcpy.hpp', + 'sprout/cstring/memmove.hpp', + 'sprout/cstring/memset.hpp', + 'sprout/cstring/strcat.hpp', + 'sprout/cstring/strchr.hpp', + 'sprout/cstring/strcmp.hpp', + 'sprout/cstring/strcoll.hpp', + 'sprout/cstring/strcpy.hpp', + 'sprout/cstring/strcspn.hpp', + 'sprout/cstring/strlen.hpp', + 'sprout/cstring/strncat.hpp', + 'sprout/cstring/strncmp.hpp', + 'sprout/cstring/strncpy.hpp', + 'sprout/cstring/strpbrk.hpp', + 'sprout/cstring/strrchr.hpp', + 'sprout/cstring/strspn.hpp', + 'sprout/cstring/strstr.hpp', + 'sprout/ctime.hpp', + 'sprout/ctime/difftime.hpp', + 'sprout/ctime/to_time_t.hpp', + 'sprout/ctype.hpp', + 'sprout/ctype/ascii.hpp', + 'sprout/ctype/functor.hpp', + 'sprout/ctype/mask.hpp', + 'sprout/ctype/wascii.hpp', + 'sprout/current_function.hpp', + 'sprout/cwchar.hpp', + 'sprout/cwchar/wcscat.hpp', + 'sprout/cwchar/wcschr.hpp', + 'sprout/cwchar/wcscmp.hpp', + 'sprout/cwchar/wcscoll.hpp', + 'sprout/cwchar/wcscpy.hpp', + 'sprout/cwchar/wcscspn.hpp', + 'sprout/cwchar/wcslen.hpp', + 'sprout/cwchar/wcsncat.hpp', + 'sprout/cwchar/wcsncmp.hpp', + 'sprout/cwchar/wcsncpy.hpp', + 'sprout/cwchar/wcspbrk.hpp', + 'sprout/cwchar/wcsrchr.hpp', + 'sprout/cwchar/wcsspn.hpp', + 'sprout/cwchar/wcsstr.hpp', + 'sprout/cwchar/wmemchr.hpp', + 'sprout/cwchar/wmemcmp.hpp', + 'sprout/cwchar/wmemcpy.hpp', + 'sprout/cwchar/wmemmove.hpp', + 'sprout/cwchar/wmemset.hpp', + 'sprout/cwctype.hpp', + 'sprout/darkroom.hpp', + 'sprout/darkroom/access.hpp', + 'sprout/darkroom/access/access.hpp', + 'sprout/darkroom/access/traits.hpp', + 'sprout/darkroom/cameras.hpp', + 'sprout/darkroom/cameras/angle_of_view.hpp', + 'sprout/darkroom/cameras/calculate.hpp', + 'sprout/darkroom/cameras/simple_camera.hpp', + 'sprout/darkroom/colors.hpp', + 'sprout/darkroom/colors/rgb.hpp', + 'sprout/darkroom/coords.hpp', + 'sprout/darkroom/coords/vector.hpp', + 'sprout/darkroom/intersects.hpp', + 'sprout/darkroom/intersects/intersection.hpp', + 'sprout/darkroom/lights.hpp', + 'sprout/darkroom/lights/ambient_light.hpp', + 'sprout/darkroom/lights/calculate.hpp', + 'sprout/darkroom/lights/light_list.hpp', + 'sprout/darkroom/lights/parallel_light.hpp', + 'sprout/darkroom/lights/point_light.hpp', + 'sprout/darkroom/load/texture.hpp', + 'sprout/darkroom/materials.hpp', + 'sprout/darkroom/materials/calculate.hpp', + 'sprout/darkroom/materials/interpolation.hpp', + 'sprout/darkroom/materials/material.hpp', + 'sprout/darkroom/materials/plaid.hpp', + 'sprout/darkroom/materials/texture_map.hpp', + 'sprout/darkroom/materials/uniform.hpp', + 'sprout/darkroom/objects.hpp', + 'sprout/darkroom/objects/aa_plane.hpp', + 'sprout/darkroom/objects/intersect.hpp', + 'sprout/darkroom/objects/object_list.hpp', + 'sprout/darkroom/objects/polygon.hpp', + 'sprout/darkroom/objects/polygon/triangle.hpp', + 'sprout/darkroom/objects/sphere.hpp', + 'sprout/darkroom/pixels.hpp', + 'sprout/darkroom/pixels/generate.hpp', + 'sprout/darkroom/rays.hpp', + 'sprout/darkroom/rays/ray.hpp', + 'sprout/darkroom/renderers.hpp', + 'sprout/darkroom/renderers/calculate.hpp', + 'sprout/darkroom/renderers/infinity.hpp', + 'sprout/darkroom/renderers/whitted_style.hpp', + 'sprout/darkroom/textures.hpp', + 'sprout/darkroom/textures/texture.hpp', + 'sprout/darkroom/tracers.hpp', + 'sprout/darkroom/tracers/calculate.hpp', + 'sprout/darkroom/tracers/raytracer.hpp', + 'sprout/detail/algorithm/count_n.hpp', + 'sprout/detail/algorithm/count_n_if.hpp', + 'sprout/detail/algorithm/lexicographical_compare.hpp', + 'sprout/detail/algorithm/mask_index.hpp', + 'sprout/detail/algorithm/overlap_count.hpp', + 'sprout/detail/algorithm/search_one.hpp', + 'sprout/detail/algorithm/search_one_rev.hpp', + 'sprout/detail/algorithm/set_overlap_count.hpp', + 'sprout/detail/algorithm_min_max.hpp', + 'sprout/detail/call_traits.hpp', + 'sprout/detail/char_conversion.hpp', + 'sprout/detail/char_literal.hpp', + 'sprout/detail/char_type_of_consecutive.hpp', + 'sprout/detail/container_complate.hpp', + 'sprout/detail/container_complate_backward.hpp', + 'sprout/detail/digits_to_int.hpp', + 'sprout/detail/do_nothing_statement.hpp', + 'sprout/detail/functional/const_subscript.hpp', + 'sprout/detail/integer.hpp', + 'sprout/detail/integer/integer_mask.hpp', + 'sprout/detail/integer/static_log2.hpp', + 'sprout/detail/io/ios_state.hpp', + 'sprout/detail/io_fwd.hpp', + 'sprout/detail/literal_def.hpp', + 'sprout/detail/math/float.hpp', + 'sprout/detail/math/int.hpp', + 'sprout/detail/nil_base.hpp', + 'sprout/detail/one_type.hpp', + 'sprout/detail/param_at.hpp', + 'sprout/detail/pow.hpp', + 'sprout/detail/predef.hpp', + 'sprout/detail/sizeof.hpp', + 'sprout/detail/static_size.hpp', + 'sprout/detail/str.hpp', + 'sprout/detail/udl_namespace.hpp', + 'sprout/endian_traits.hpp', + 'sprout/forward_clist.hpp', + 'sprout/functional.hpp', + 'sprout/functional/adaptor.hpp', + 'sprout/functional/address_of.hpp', + 'sprout/functional/arithmetic.hpp', + 'sprout/functional/assign.hpp', + 'sprout/functional/assignment.hpp', + 'sprout/functional/base.hpp', + 'sprout/functional/binary_function.hpp', + 'sprout/functional/bind.hpp', + 'sprout/functional/bind/bind.hpp', + 'sprout/functional/bind/literals.hpp', + 'sprout/functional/bind/placeholder.hpp', + 'sprout/functional/bind1st.hpp', + 'sprout/functional/bind2nd.hpp', + 'sprout/functional/binder.hpp', + 'sprout/functional/bit_and.hpp', + 'sprout/functional/bit_and_assign.hpp', + 'sprout/functional/bit_not.hpp', + 'sprout/functional/bit_or.hpp', + 'sprout/functional/bit_or_assign.hpp', + 'sprout/functional/bit_xor.hpp', + 'sprout/functional/bit_xor_assign.hpp', + 'sprout/functional/bitwise.hpp', + 'sprout/functional/call_fun.hpp', + 'sprout/functional/comma.hpp', + 'sprout/functional/comparison.hpp', + 'sprout/functional/cond.hpp', + 'sprout/functional/dereference.hpp', + 'sprout/functional/divides.hpp', + 'sprout/functional/divides_assign.hpp', + 'sprout/functional/equal_to.hpp', + 'sprout/functional/equiv.hpp', + 'sprout/functional/functor.hpp', + 'sprout/functional/greater.hpp', + 'sprout/functional/greater_equal.hpp', + 'sprout/functional/hash.hpp', + 'sprout/functional/hash/boost/array.hpp', + 'sprout/functional/hash/detail/hash_float.hpp', + 'sprout/functional/hash/hash.hpp', + 'sprout/functional/hash/hash_combine.hpp', + 'sprout/functional/hash/hash_fwd.hpp', + 'sprout/functional/hash/hash_range.hpp', + 'sprout/functional/hash/hash_value.hpp', + 'sprout/functional/hash/hash_value_traits.hpp', + 'sprout/functional/hash/hash_values.hpp', + 'sprout/functional/hash/sscrisk/cel/array.hpp', + 'sprout/functional/hash/sscrisk/cel/utility.hpp', + 'sprout/functional/hash/std/array.hpp', + 'sprout/functional/hash/std/complex.hpp', + 'sprout/functional/hash/std/utility.hpp', + 'sprout/functional/hash/to_hash.hpp', + 'sprout/functional/hash_fwd.hpp', + 'sprout/functional/inc_dec.hpp', + 'sprout/functional/invoke.hpp', + 'sprout/functional/less.hpp', + 'sprout/functional/less_equal.hpp', + 'sprout/functional/logical.hpp', + 'sprout/functional/logical_and.hpp', + 'sprout/functional/logical_not.hpp', + 'sprout/functional/logical_or.hpp', + 'sprout/functional/mem_fn.hpp', + 'sprout/functional/mem_fun.hpp', + 'sprout/functional/mem_fun_ref.hpp', + 'sprout/functional/member.hpp', + 'sprout/functional/member_pointer.hpp', + 'sprout/functional/members.hpp', + 'sprout/functional/minus.hpp', + 'sprout/functional/minus_assign.hpp', + 'sprout/functional/modulus.hpp', + 'sprout/functional/modulus_assign.hpp', + 'sprout/functional/multiplies.hpp', + 'sprout/functional/multiplies_assign.hpp', + 'sprout/functional/negate.hpp', + 'sprout/functional/negator.hpp', + 'sprout/functional/not1.hpp', + 'sprout/functional/not2.hpp', + 'sprout/functional/not_equal_to.hpp', + 'sprout/functional/plus.hpp', + 'sprout/functional/plus_assign.hpp', + 'sprout/functional/polymorphic.hpp', + 'sprout/functional/polymorphic/address_of.hpp', + 'sprout/functional/polymorphic/arithmetic.hpp', + 'sprout/functional/polymorphic/assign.hpp', + 'sprout/functional/polymorphic/assignment.hpp', + 'sprout/functional/polymorphic/bind1st.hpp', + 'sprout/functional/polymorphic/bind2nd.hpp', + 'sprout/functional/polymorphic/binder.hpp', + 'sprout/functional/polymorphic/bit_and.hpp', + 'sprout/functional/polymorphic/bit_and_assign.hpp', + 'sprout/functional/polymorphic/bit_not.hpp', + 'sprout/functional/polymorphic/bit_or.hpp', + 'sprout/functional/polymorphic/bit_or_assign.hpp', + 'sprout/functional/polymorphic/bit_xor.hpp', + 'sprout/functional/polymorphic/bit_xor_assign.hpp', + 'sprout/functional/polymorphic/bitwise.hpp', + 'sprout/functional/polymorphic/call_fun.hpp', + 'sprout/functional/polymorphic/comma.hpp', + 'sprout/functional/polymorphic/comparison.hpp', + 'sprout/functional/polymorphic/cond.hpp', + 'sprout/functional/polymorphic/dereference.hpp', + 'sprout/functional/polymorphic/divides.hpp', + 'sprout/functional/polymorphic/divides_assign.hpp', + 'sprout/functional/polymorphic/equal_to.hpp', + 'sprout/functional/polymorphic/functor.hpp', + 'sprout/functional/polymorphic/greater.hpp', + 'sprout/functional/polymorphic/greater_equal.hpp', + 'sprout/functional/polymorphic/inc_dec.hpp', + 'sprout/functional/polymorphic/less.hpp', + 'sprout/functional/polymorphic/less_equal.hpp', + 'sprout/functional/polymorphic/logical.hpp', + 'sprout/functional/polymorphic/logical_and.hpp', + 'sprout/functional/polymorphic/logical_not.hpp', + 'sprout/functional/polymorphic/logical_or.hpp', + 'sprout/functional/polymorphic/member.hpp', + 'sprout/functional/polymorphic/member_pointer.hpp', + 'sprout/functional/polymorphic/members.hpp', + 'sprout/functional/polymorphic/minus.hpp', + 'sprout/functional/polymorphic/minus_assign.hpp', + 'sprout/functional/polymorphic/modulus.hpp', + 'sprout/functional/polymorphic/modulus_assign.hpp', + 'sprout/functional/polymorphic/multiplies.hpp', + 'sprout/functional/polymorphic/multiplies_assign.hpp', + 'sprout/functional/polymorphic/negate.hpp', + 'sprout/functional/polymorphic/not_equal_to.hpp', + 'sprout/functional/polymorphic/plus.hpp', + 'sprout/functional/polymorphic/plus_assign.hpp', + 'sprout/functional/polymorphic/posite.hpp', + 'sprout/functional/polymorphic/post_decrement.hpp', + 'sprout/functional/polymorphic/post_increment.hpp', + 'sprout/functional/polymorphic/pre_decrement.hpp', + 'sprout/functional/polymorphic/pre_increment.hpp', + 'sprout/functional/polymorphic/reference.hpp', + 'sprout/functional/polymorphic/shift_left.hpp', + 'sprout/functional/polymorphic/shift_left_assign.hpp', + 'sprout/functional/polymorphic/shift_right.hpp', + 'sprout/functional/polymorphic/shift_right_assign.hpp', + 'sprout/functional/polymorphic/subscript.hpp', + 'sprout/functional/polymorphic/various.hpp', + 'sprout/functional/posite.hpp', + 'sprout/functional/post_decrement.hpp', + 'sprout/functional/post_increment.hpp', + 'sprout/functional/pre_decrement.hpp', + 'sprout/functional/pre_increment.hpp', + 'sprout/functional/ptr_fun.hpp', + 'sprout/functional/ref.hpp', + 'sprout/functional/reference.hpp', + 'sprout/functional/shift_left.hpp', + 'sprout/functional/shift_left_assign.hpp', + 'sprout/functional/shift_right.hpp', + 'sprout/functional/shift_right_assign.hpp', + 'sprout/functional/subscript.hpp', + 'sprout/functional/transparent.hpp', + 'sprout/functional/type_traits.hpp', + 'sprout/functional/type_traits/has_type.hpp', + 'sprout/functional/type_traits/inherit_if_type.hpp', + 'sprout/functional/type_traits/is_strict_function.hpp', + 'sprout/functional/type_traits/is_transparent_function.hpp', + 'sprout/functional/type_traits/weak_result_type.hpp', + 'sprout/functional/unary_function.hpp', + 'sprout/functional/various.hpp', + 'sprout/generator.hpp', + 'sprout/generator/access_functions.hpp', + 'sprout/generator/access_functions_fwd.hpp', + 'sprout/generator/detail/generated_value.hpp', + 'sprout/generator/detail/next_generator.hpp', + 'sprout/generator/detail/next_value.hpp', + 'sprout/generator/functions.hpp', + 'sprout/generator/generate_functions.hpp', + 'sprout/generator/generate_functions_fwd.hpp', + 'sprout/generator/generated_value.hpp', + 'sprout/generator/generator_access_traits.hpp', + 'sprout/generator/generator_generate_traits.hpp', + 'sprout/generator/next_generator.hpp', + 'sprout/generator/next_value.hpp', + 'sprout/generator/results.hpp', + 'sprout/generator/traits.hpp', + 'sprout/generator/traits_fwd.hpp', + 'sprout/index_tuple.hpp', + 'sprout/index_tuple/class.hpp', + 'sprout/index_tuple/enable_make_indexes.hpp', + 'sprout/index_tuple/index_n.hpp', + 'sprout/index_tuple/index_pack.hpp', + 'sprout/index_tuple/index_range.hpp', + 'sprout/index_tuple/index_sequence.hpp', + 'sprout/index_tuple/index_sequence_for.hpp', + 'sprout/index_tuple/index_t.hpp', + 'sprout/index_tuple/index_tuple.hpp', + 'sprout/index_tuple/integer_n.hpp', + 'sprout/index_tuple/integer_pack.hpp', + 'sprout/index_tuple/integer_range.hpp', + 'sprout/index_tuple/integer_sequence.hpp', + 'sprout/index_tuple/literals.hpp', + 'sprout/index_tuple/make_index_sequence.hpp', + 'sprout/index_tuple/make_index_tuple.hpp', + 'sprout/index_tuple/make_indexes.hpp', + 'sprout/index_tuple/make_integer_sequence.hpp', + 'sprout/index_tuple/metafunction.hpp', + 'sprout/index_tuple/tuple.hpp', + 'sprout/index_tuple/utility.hpp', + 'sprout/integer.hpp', + 'sprout/integer/carry_to_exp2.hpp', + 'sprout/integer/integer_digits.hpp', + 'sprout/integer/static_pow.hpp', + 'sprout/io.hpp', + 'sprout/iterator.hpp', + 'sprout/iterator/adaptor.hpp', + 'sprout/iterator/adjacent_filter_iterator.hpp', + 'sprout/iterator/advance.hpp', + 'sprout/iterator/alternate_iterator.hpp', + 'sprout/iterator/amplitude_spectrum_iterator.hpp', + 'sprout/iterator/back_insert_iterator.hpp', + 'sprout/iterator/bytes_iterator.hpp', + 'sprout/iterator/clamp_iterator.hpp', + 'sprout/iterator/const_iterator_cast.hpp', + 'sprout/iterator/const_reference_cast.hpp', + 'sprout/iterator/counting_iterator.hpp', + 'sprout/iterator/detail/iterator_base.hpp', + 'sprout/iterator/detail/iterator_to_pointer.hpp', + 'sprout/iterator/dft.hpp', + 'sprout/iterator/dft_iterator.hpp', + 'sprout/iterator/distance.hpp', + 'sprout/iterator/filter_iterator.hpp', + 'sprout/iterator/front_insert_iterator.hpp', + 'sprout/iterator/generator_iterator.hpp', + 'sprout/iterator/idft_iterator.hpp', + 'sprout/iterator/index_iterator.hpp', + 'sprout/iterator/indexed_iterator.hpp', + 'sprout/iterator/insert_iterator.hpp', + 'sprout/iterator/insert_range_iterator.hpp', + 'sprout/iterator/inserter.hpp', + 'sprout/iterator/iterator.hpp', + 'sprout/iterator/iterator_traits.hpp', + 'sprout/iterator/joint_iterator.hpp', + 'sprout/iterator/merge_iterator.hpp', + 'sprout/iterator/move_iterator.hpp', + 'sprout/iterator/next.hpp', + 'sprout/iterator/next_fwd.hpp', + 'sprout/iterator/next_iterator.hpp', + 'sprout/iterator/operation.hpp', + 'sprout/iterator/phase_spectrum_iterator.hpp', + 'sprout/iterator/predefined.hpp', + 'sprout/iterator/prev.hpp', + 'sprout/iterator/prev_fwd.hpp', + 'sprout/iterator/ptr_index_iterator.hpp', + 'sprout/iterator/remake_iterator.hpp', + 'sprout/iterator/remove_if_iterator.hpp', + 'sprout/iterator/remove_iterator.hpp', + 'sprout/iterator/replace_if_iterator.hpp', + 'sprout/iterator/replace_iterator.hpp', + 'sprout/iterator/reverse_iterator.hpp', + 'sprout/iterator/sawtooth_iterator.hpp', + 'sprout/iterator/set_difference_iterator.hpp', + 'sprout/iterator/set_intersection_iterator.hpp', + 'sprout/iterator/set_symmetric_difference_iterator.hpp', + 'sprout/iterator/set_union_iterator.hpp', + 'sprout/iterator/sinusoid_iterator.hpp', + 'sprout/iterator/size_enum_iterator.hpp', + 'sprout/iterator/square_iterator.hpp', + 'sprout/iterator/step_iterator.hpp', + 'sprout/iterator/string.hpp', + 'sprout/iterator/to_lower_iterator.hpp', + 'sprout/iterator/to_upper_iterator.hpp', + 'sprout/iterator/transform_iterator.hpp', + 'sprout/iterator/triangle_iterator.hpp', + 'sprout/iterator/type_traits.hpp', + 'sprout/iterator/type_traits/category.hpp', + 'sprout/iterator/type_traits/common.hpp', + 'sprout/iterator/type_traits/is_constant_distance_iterator.hpp', + 'sprout/iterator/type_traits/is_iterator.hpp', + 'sprout/iterator/type_traits/is_iterator_category_of.hpp', + 'sprout/iterator/type_traits/is_iterator_of.hpp', + 'sprout/iterator/unique_iterator.hpp', + 'sprout/iterator/value_iterator.hpp', + 'sprout/iterator/valued_iterator.hpp', + 'sprout/iterator/various.hpp', + 'sprout/iterator/wave.hpp', + 'sprout/iterator/while_iterator.hpp', + 'sprout/limits.hpp', + 'sprout/logic.hpp', + 'sprout/logic/tribool.hpp', + 'sprout/logic/tribool/hash.hpp', + 'sprout/logic/tribool/io.hpp', + 'sprout/logic/tribool/tribool.hpp', + 'sprout/logic/tribool/tribool_fwd.hpp', + 'sprout/logic/tribool_fwd.hpp', + 'sprout/math.hpp', + 'sprout/math/abs.hpp', + 'sprout/math/acos.hpp', + 'sprout/math/acosh.hpp', + 'sprout/math/asin.hpp', + 'sprout/math/asinh.hpp', + 'sprout/math/atan.hpp', + 'sprout/math/atan2.hpp', + 'sprout/math/atanh.hpp', + 'sprout/math/bernoulli.hpp', + 'sprout/math/cbrt.hpp', + 'sprout/math/ceil.hpp', + 'sprout/math/classifications.hpp', + 'sprout/math/cmath.hpp', + 'sprout/math/common_factor.hpp', + 'sprout/math/compare.hpp', + 'sprout/math/comparisons.hpp', + 'sprout/math/constant_variables.hpp', + 'sprout/math/constants.hpp', + 'sprout/math/copysign.hpp', + 'sprout/math/cos.hpp', + 'sprout/math/cosh.hpp', + 'sprout/math/curve.hpp', + 'sprout/math/curve/bezier.hpp', + 'sprout/math/curve/catmull_rom_spline.hpp', + 'sprout/math/curve/curve_point.hpp', + 'sprout/math/detail/config.hpp', + 'sprout/math/detail/cosp.hpp', + 'sprout/math/detail/float_compute.hpp', + 'sprout/math/detail/sinp.hpp', + 'sprout/math/equal_to.hpp', + 'sprout/math/erf.hpp', + 'sprout/math/erfc.hpp', + 'sprout/math/error.hpp', + 'sprout/math/exp.hpp', + 'sprout/math/exp10.hpp', + 'sprout/math/exp2.hpp', + 'sprout/math/expm1.hpp', + 'sprout/math/exponential.hpp', + 'sprout/math/fabs.hpp', + 'sprout/math/factorial.hpp', + 'sprout/math/fdim.hpp', + 'sprout/math/float2_exponent.hpp', + 'sprout/math/float2_sig_exp.hpp', + 'sprout/math/float2_significand.hpp', + 'sprout/math/float_exponent.hpp', + 'sprout/math/float_sig_exp.hpp', + 'sprout/math/float_significand.hpp', + 'sprout/math/floating_point.hpp', + 'sprout/math/floor.hpp', + 'sprout/math/fma.hpp', + 'sprout/math/fmax.hpp', + 'sprout/math/fmin.hpp', + 'sprout/math/fmod.hpp', + 'sprout/math/fpclassify.hpp', + 'sprout/math/frac_int.hpp', + 'sprout/math/fractional_part.hpp', + 'sprout/math/functions.hpp', + 'sprout/math/gamma.hpp', + 'sprout/math/gcd.hpp', + 'sprout/math/greater.hpp', + 'sprout/math/greater_equal.hpp', + 'sprout/math/hyperbolic.hpp', + 'sprout/math/hypot.hpp', + 'sprout/math/iceil.hpp', + 'sprout/math/ifloor.hpp', + 'sprout/math/ilogb.hpp', + 'sprout/math/ilogb2.hpp', + 'sprout/math/integer.hpp', + 'sprout/math/integer_part.hpp', + 'sprout/math/iround.hpp', + 'sprout/math/is_even.hpp', + 'sprout/math/is_integer.hpp', + 'sprout/math/is_odd.hpp', + 'sprout/math/isfinite.hpp', + 'sprout/math/isgreater.hpp', + 'sprout/math/isgreaterequal.hpp', + 'sprout/math/isinf.hpp', + 'sprout/math/isless.hpp', + 'sprout/math/islessequal.hpp', + 'sprout/math/islessgreater.hpp', + 'sprout/math/isnan.hpp', + 'sprout/math/isnormal.hpp', + 'sprout/math/issubnormal.hpp', + 'sprout/math/isunordered.hpp', + 'sprout/math/iszero.hpp', + 'sprout/math/itrunc.hpp', + 'sprout/math/lcm.hpp', + 'sprout/math/ldexp.hpp', + 'sprout/math/less.hpp', + 'sprout/math/less_equal.hpp', + 'sprout/math/lgamma.hpp', + 'sprout/math/llround.hpp', + 'sprout/math/log.hpp', + 'sprout/math/log10.hpp', + 'sprout/math/log1p.hpp', + 'sprout/math/log2.hpp', + 'sprout/math/log_a.hpp', + 'sprout/math/logb.hpp', + 'sprout/math/logb2.hpp', + 'sprout/math/lround.hpp', + 'sprout/math/manipulations.hpp', + 'sprout/math/minmax.hpp', + 'sprout/math/muladd.hpp', + 'sprout/math/nearest.hpp', + 'sprout/math/not_equal_to.hpp', + 'sprout/math/pow.hpp', + 'sprout/math/power.hpp', + 'sprout/math/quaternion.hpp', + 'sprout/math/quaternion/abs.hpp', + 'sprout/math/quaternion/arithmetic_operators.hpp', + 'sprout/math/quaternion/conj.hpp', + 'sprout/math/quaternion/container.hpp', + 'sprout/math/quaternion/cos.hpp', + 'sprout/math/quaternion/cosh.hpp', + 'sprout/math/quaternion/creations.hpp', + 'sprout/math/quaternion/cylindrical.hpp', + 'sprout/math/quaternion/cylindrospherical.hpp', + 'sprout/math/quaternion/detail/abs_max.hpp', + 'sprout/math/quaternion/detail/mul.hpp', + 'sprout/math/quaternion/detail/sum.hpp', + 'sprout/math/quaternion/exp.hpp', + 'sprout/math/quaternion/hash.hpp', + 'sprout/math/quaternion/l1.hpp', + 'sprout/math/quaternion/literals.hpp', + 'sprout/math/quaternion/multipolar.hpp', + 'sprout/math/quaternion/norm.hpp', + 'sprout/math/quaternion/operators.hpp', + 'sprout/math/quaternion/pow.hpp', + 'sprout/math/quaternion/quaternion.hpp', + 'sprout/math/quaternion/real.hpp', + 'sprout/math/quaternion/semipolar.hpp', + 'sprout/math/quaternion/sin.hpp', + 'sprout/math/quaternion/sinh.hpp', + 'sprout/math/quaternion/spherical.hpp', + 'sprout/math/quaternion/stream_operators.hpp', + 'sprout/math/quaternion/sup.hpp', + 'sprout/math/quaternion/tan.hpp', + 'sprout/math/quaternion/tanh.hpp', + 'sprout/math/quaternion/transcendentals.hpp', + 'sprout/math/quaternion/tuple.hpp', + 'sprout/math/quaternion/type_traits.hpp', + 'sprout/math/quaternion/unreal.hpp', + 'sprout/math/quaternion/values.hpp', + 'sprout/math/quotient.hpp', + 'sprout/math/rem_quo.hpp', + 'sprout/math/remainder.hpp', + 'sprout/math/remainders.hpp', + 'sprout/math/round.hpp', + 'sprout/math/scalbln.hpp', + 'sprout/math/scalbn.hpp', + 'sprout/math/sigmoid.hpp', + 'sprout/math/signbit.hpp', + 'sprout/math/sin.hpp', + 'sprout/math/sinh.hpp', + 'sprout/math/sqrt.hpp', + 'sprout/math/tan.hpp', + 'sprout/math/tanh.hpp', + 'sprout/math/tgamma.hpp', + 'sprout/math/trigonometric.hpp', + 'sprout/math/trunc.hpp', + 'sprout/memory.hpp', + 'sprout/memory/addressof.hpp', + 'sprout/memory/exempt_ptr.hpp', + 'sprout/memory/get_pointer.hpp', + 'sprout/memory/observer_ptr.hpp', + 'sprout/memory/pointer_cast.hpp', + 'sprout/net.hpp', + 'sprout/net/endian.hpp', + 'sprout/none.hpp', + 'sprout/numeric.hpp', + 'sprout/numeric/accumulate.hpp', + 'sprout/numeric/adjacent_difference.hpp', + 'sprout/numeric/cxx14.hpp', + 'sprout/numeric/cxx14/adjacent_difference.hpp', + 'sprout/numeric/cxx14/exclusive_scan.hpp', + 'sprout/numeric/cxx14/inclusive_scan.hpp', + 'sprout/numeric/cxx14/iota.hpp', + 'sprout/numeric/cxx14/partial_sum.hpp', + 'sprout/numeric/cxx14/transform_exclusive_scan.hpp', + 'sprout/numeric/cxx14/transform_inclusive_scan.hpp', + 'sprout/numeric/dft.hpp', + 'sprout/numeric/dft/amplitude_spectrum.hpp', + 'sprout/numeric/dft/amplitude_spectrum_value.hpp', + 'sprout/numeric/dft/cxx14.hpp', + 'sprout/numeric/dft/cxx14/amplitude_spectrum.hpp', + 'sprout/numeric/dft/cxx14/phase_spectrum.hpp', + 'sprout/numeric/dft/cxx14/sawtooth.hpp', + 'sprout/numeric/dft/cxx14/sinusoid.hpp', + 'sprout/numeric/dft/cxx14/spectrum.hpp', + 'sprout/numeric/dft/cxx14/square.hpp', + 'sprout/numeric/dft/cxx14/triangle.hpp', + 'sprout/numeric/dft/cxx14/wave.hpp', + 'sprout/numeric/dft/detail/dft_element_gen.hpp', + 'sprout/numeric/dft/detail/sawtooth.hpp', + 'sprout/numeric/dft/detail/sinusoid.hpp', + 'sprout/numeric/dft/detail/square.hpp', + 'sprout/numeric/dft/detail/triangle.hpp', + 'sprout/numeric/dft/dft.hpp', + 'sprout/numeric/dft/dft_element.hpp', + 'sprout/numeric/dft/fit.hpp', + 'sprout/numeric/dft/fit/amplitude_spectrum.hpp', + 'sprout/numeric/dft/fit/dft.hpp', + 'sprout/numeric/dft/fit/idft.hpp', + 'sprout/numeric/dft/fit/phase_spectrum.hpp', + 'sprout/numeric/dft/fit/sawtooth.hpp', + 'sprout/numeric/dft/fit/sinusoid.hpp', + 'sprout/numeric/dft/fit/spectrum.hpp', + 'sprout/numeric/dft/fit/square.hpp', + 'sprout/numeric/dft/fit/triangle.hpp', + 'sprout/numeric/dft/fit/wave.hpp', + 'sprout/numeric/dft/fixed.hpp', + 'sprout/numeric/dft/fixed/amplitude_spectrum.hpp', + 'sprout/numeric/dft/fixed/dft.hpp', + 'sprout/numeric/dft/fixed/idft.hpp', + 'sprout/numeric/dft/fixed/phase_spectrum.hpp', + 'sprout/numeric/dft/fixed/sawtooth.hpp', + 'sprout/numeric/dft/fixed/sinusoid.hpp', + 'sprout/numeric/dft/fixed/spectrum.hpp', + 'sprout/numeric/dft/fixed/square.hpp', + 'sprout/numeric/dft/fixed/triangle.hpp', + 'sprout/numeric/dft/fixed/wave.hpp', + 'sprout/numeric/dft/idft.hpp', + 'sprout/numeric/dft/idft_element.hpp', + 'sprout/numeric/dft/modifying.hpp', + 'sprout/numeric/dft/non_modifying.hpp', + 'sprout/numeric/dft/phase_spectrum.hpp', + 'sprout/numeric/dft/phase_spectrum_value.hpp', + 'sprout/numeric/dft/sawtooth.hpp', + 'sprout/numeric/dft/sinusoid.hpp', + 'sprout/numeric/dft/spectrum.hpp', + 'sprout/numeric/dft/square.hpp', + 'sprout/numeric/dft/triangle.hpp', + 'sprout/numeric/dft/wave.hpp', + 'sprout/numeric/exclusive_scan.hpp', + 'sprout/numeric/fft.hpp', + 'sprout/numeric/fft/bitrev_table.hpp', + 'sprout/numeric/fft/coefficients.hpp', + 'sprout/numeric/fft/cxx14/fft.hpp', + 'sprout/numeric/fft/cxx14/ifft.hpp', + 'sprout/numeric/fft/fft.hpp', + 'sprout/numeric/fft/fit/bitrev_table.hpp', + 'sprout/numeric/fft/fit/fft.hpp', + 'sprout/numeric/fft/fit/ifft.hpp', + 'sprout/numeric/fft/fixed/bitrev_table.hpp', + 'sprout/numeric/fft/fixed/fft.hpp', + 'sprout/numeric/fft/fixed/ifft.hpp', + 'sprout/numeric/fft/ifft.hpp', + 'sprout/numeric/fit.hpp', + 'sprout/numeric/fit/adjacent_difference.hpp', + 'sprout/numeric/fit/exclusive_scan.hpp', + 'sprout/numeric/fit/inclusive_scan.hpp', + 'sprout/numeric/fit/iota.hpp', + 'sprout/numeric/fit/partial_sum.hpp', + 'sprout/numeric/fit/transform_exclusive_scan.hpp', + 'sprout/numeric/fit/transform_inclusive_scan.hpp', + 'sprout/numeric/fixed.hpp', + 'sprout/numeric/fixed/adjacent_difference.hpp', + 'sprout/numeric/fixed/exclusive_scan.hpp', + 'sprout/numeric/fixed/inclusive_scan.hpp', + 'sprout/numeric/fixed/iota.hpp', + 'sprout/numeric/fixed/partial_sum.hpp', + 'sprout/numeric/fixed/transform_exclusive_scan.hpp', + 'sprout/numeric/fixed/transform_inclusive_scan.hpp', + 'sprout/numeric/inclusive_scan.hpp', + 'sprout/numeric/inner_product.hpp', + 'sprout/numeric/iota.hpp', + 'sprout/numeric/modifying.hpp', + 'sprout/numeric/non_modifying.hpp', + 'sprout/numeric/partial_sum.hpp', + 'sprout/numeric/reduce.hpp', + 'sprout/numeric/transform_exclusive_scan.hpp', + 'sprout/numeric/transform_inclusive_scan.hpp', + 'sprout/numeric/transform_reduce.hpp', + 'sprout/operation.hpp', + 'sprout/operation/append.hpp', + 'sprout/operation/append_back.hpp', + 'sprout/operation/append_front.hpp', + 'sprout/operation/erase.hpp', + 'sprout/operation/erase_n.hpp', + 'sprout/operation/fit.hpp', + 'sprout/operation/fit/append.hpp', + 'sprout/operation/fit/append_back.hpp', + 'sprout/operation/fit/append_front.hpp', + 'sprout/operation/fit/erase.hpp', + 'sprout/operation/fit/erase_n.hpp', + 'sprout/operation/fit/insert.hpp', + 'sprout/operation/fit/insert_n.hpp', + 'sprout/operation/fit/pop_back.hpp', + 'sprout/operation/fit/pop_back_n.hpp', + 'sprout/operation/fit/pop_front.hpp', + 'sprout/operation/fit/pop_front_n.hpp', + 'sprout/operation/fit/push_back.hpp', + 'sprout/operation/fit/push_back_n.hpp', + 'sprout/operation/fit/push_front.hpp', + 'sprout/operation/fit/push_front_n.hpp', + 'sprout/operation/fit/realign.hpp', + 'sprout/operation/fit/realign_to.hpp', + 'sprout/operation/fit/resize.hpp', + 'sprout/operation/fit/resize_backward.hpp', + 'sprout/operation/fit/set.hpp', + 'sprout/operation/fixed.hpp', + 'sprout/operation/fixed/append.hpp', + 'sprout/operation/fixed/append_back.hpp', + 'sprout/operation/fixed/append_front.hpp', + 'sprout/operation/fixed/erase.hpp', + 'sprout/operation/fixed/erase_n.hpp', + 'sprout/operation/fixed/insert.hpp', + 'sprout/operation/fixed/insert_n.hpp', + 'sprout/operation/fixed/pop_back.hpp', + 'sprout/operation/fixed/pop_back_n.hpp', + 'sprout/operation/fixed/pop_front.hpp', + 'sprout/operation/fixed/pop_front_n.hpp', + 'sprout/operation/fixed/push_back.hpp', + 'sprout/operation/fixed/push_back_n.hpp', + 'sprout/operation/fixed/push_front.hpp', + 'sprout/operation/fixed/push_front_n.hpp', + 'sprout/operation/fixed/realign.hpp', + 'sprout/operation/fixed/realign_to.hpp', + 'sprout/operation/fixed/resize.hpp', + 'sprout/operation/fixed/resize_backward.hpp', + 'sprout/operation/fixed/set.hpp', + 'sprout/operation/insert.hpp', + 'sprout/operation/insert_n.hpp', + 'sprout/operation/pop_back.hpp', + 'sprout/operation/pop_back_n.hpp', + 'sprout/operation/pop_front.hpp', + 'sprout/operation/pop_front_n.hpp', + 'sprout/operation/push_back.hpp', + 'sprout/operation/push_back_n.hpp', + 'sprout/operation/push_front.hpp', + 'sprout/operation/push_front_n.hpp', + 'sprout/operation/realign.hpp', + 'sprout/operation/realign_to.hpp', + 'sprout/operation/resize.hpp', + 'sprout/operation/resize_backward.hpp', + 'sprout/operation/set.hpp', + 'sprout/optional.hpp', + 'sprout/optional/comparison.hpp', + 'sprout/optional/container.hpp', + 'sprout/optional/exceptions.hpp', + 'sprout/optional/get.hpp', + 'sprout/optional/hash.hpp', + 'sprout/optional/in_place.hpp', + 'sprout/optional/io.hpp', + 'sprout/optional/make_optional.hpp', + 'sprout/optional/nullopt.hpp', + 'sprout/optional/optional.hpp', + 'sprout/pit.hpp', + 'sprout/pit/comparison.hpp', + 'sprout/pit/container.hpp', + 'sprout/pit/hash.hpp', + 'sprout/pit/pit.hpp', + 'sprout/pit/tuple.hpp', + 'sprout/pit/type_traits.hpp', + 'sprout/predef.hpp', + 'sprout/predef/architecture.hpp', + 'sprout/predef/architecture/alpha.hpp', + 'sprout/predef/architecture/arm.hpp', + 'sprout/predef/architecture/blackfin.hpp', + 'sprout/predef/architecture/convex.hpp', + 'sprout/predef/architecture/ia64.hpp', + 'sprout/predef/architecture/m68k.hpp', + 'sprout/predef/architecture/mips.hpp', + 'sprout/predef/architecture/parisc.hpp', + 'sprout/predef/architecture/ppc.hpp', + 'sprout/predef/architecture/pyramid.hpp', + 'sprout/predef/architecture/rs6k.hpp', + 'sprout/predef/architecture/sparc.hpp', + 'sprout/predef/architecture/superh.hpp', + 'sprout/predef/architecture/sys370.hpp', + 'sprout/predef/architecture/sys390.hpp', + 'sprout/predef/architecture/x86.hpp', + 'sprout/predef/architecture/x86/32.hpp', + 'sprout/predef/architecture/x86/64.hpp', + 'sprout/predef/architecture/z.hpp', + 'sprout/predef/compiler.hpp', + 'sprout/predef/compiler/borland.hpp', + 'sprout/predef/compiler/clang.hpp', + 'sprout/predef/compiler/comeau.hpp', + 'sprout/predef/compiler/compaq.hpp', + 'sprout/predef/compiler/diab.hpp', + 'sprout/predef/compiler/digitalmars.hpp', + 'sprout/predef/compiler/dignus.hpp', + 'sprout/predef/compiler/edg.hpp', + 'sprout/predef/compiler/ekopath.hpp', + 'sprout/predef/compiler/gcc.hpp', + 'sprout/predef/compiler/gcc_xml.hpp', + 'sprout/predef/compiler/greenhills.hpp', + 'sprout/predef/compiler/hp_acc.hpp', + 'sprout/predef/compiler/iar.hpp', + 'sprout/predef/compiler/ibm.hpp', + 'sprout/predef/compiler/intel.hpp', + 'sprout/predef/compiler/kai.hpp', + 'sprout/predef/compiler/llvm.hpp', + 'sprout/predef/compiler/metaware.hpp', + 'sprout/predef/compiler/metrowerks.hpp', + 'sprout/predef/compiler/microtec.hpp', + 'sprout/predef/compiler/mpw.hpp', + 'sprout/predef/compiler/palm.hpp', + 'sprout/predef/compiler/pgi.hpp', + 'sprout/predef/compiler/sgi_mipspro.hpp', + 'sprout/predef/compiler/sunpro.hpp', + 'sprout/predef/compiler/tendra.hpp', + 'sprout/predef/compiler/visualc.hpp', + 'sprout/predef/compiler/watcom.hpp', + 'sprout/predef/detail/comp_detected.hpp', + 'sprout/predef/detail/endian_compat.hpp', + 'sprout/predef/detail/os_detected.hpp', + 'sprout/predef/detail/platform_detected.hpp', + 'sprout/predef/hardware.hpp', + 'sprout/predef/hardware/simd.hpp', + 'sprout/predef/hardware/simd/arm.hpp', + 'sprout/predef/hardware/simd/arm/versions.hpp', + 'sprout/predef/hardware/simd/ppc.hpp', + 'sprout/predef/hardware/simd/ppc/versions.hpp', + 'sprout/predef/hardware/simd/x86.hpp', + 'sprout/predef/hardware/simd/x86/versions.hpp', + 'sprout/predef/hardware/simd/x86_amd.hpp', + 'sprout/predef/hardware/simd/x86_amd/versions.hpp', + 'sprout/predef/language.hpp', + 'sprout/predef/language/objc.hpp', + 'sprout/predef/language/stdc.hpp', + 'sprout/predef/language/stdcpp.hpp', + 'sprout/predef/library.hpp', + 'sprout/predef/library/c.hpp', + 'sprout/predef/library/c/gnu.hpp', + 'sprout/predef/library/c/prefix.hpp', + 'sprout/predef/library/c/uc.hpp', + 'sprout/predef/library/c/vms.hpp', + 'sprout/predef/library/c/zos.hpp', + 'sprout/predef/library/std.hpp', + 'sprout/predef/library/std/cxx.hpp', + 'sprout/predef/library/std/dinkumware.hpp', + 'sprout/predef/library/std/libcomo.hpp', + 'sprout/predef/library/std/modena.hpp', + 'sprout/predef/library/std/msl.hpp', + 'sprout/predef/library/std/prefix.hpp', + 'sprout/predef/library/std/roguewave.hpp', + 'sprout/predef/library/std/sgi.hpp', + 'sprout/predef/library/std/stdcpp3.hpp', + 'sprout/predef/library/std/stlport.hpp', + 'sprout/predef/library/std/vacpp.hpp', + 'sprout/predef/make.hpp', + 'sprout/predef/os.hpp', + 'sprout/predef/os/aix.hpp', + 'sprout/predef/os/amigaos.hpp', + 'sprout/predef/os/android.hpp', + 'sprout/predef/os/beos.hpp', + 'sprout/predef/os/bsd.hpp', + 'sprout/predef/os/bsd/bsdi.hpp', + 'sprout/predef/os/bsd/dragonfly.hpp', + 'sprout/predef/os/bsd/free.hpp', + 'sprout/predef/os/bsd/net.hpp', + 'sprout/predef/os/bsd/open.hpp', + 'sprout/predef/os/cygwin.hpp', + 'sprout/predef/os/haiku.hpp', + 'sprout/predef/os/hpux.hpp', + 'sprout/predef/os/ios.hpp', + 'sprout/predef/os/irix.hpp', + 'sprout/predef/os/linux.hpp', + 'sprout/predef/os/macos.hpp', + 'sprout/predef/os/os400.hpp', + 'sprout/predef/os/qnxnto.hpp', + 'sprout/predef/os/solaris.hpp', + 'sprout/predef/os/unix.hpp', + 'sprout/predef/os/vms.hpp', + 'sprout/predef/os/windows.hpp', + 'sprout/predef/other.hpp', + 'sprout/predef/other/endian.hpp', + 'sprout/predef/platform.hpp', + 'sprout/predef/platform/mingw.hpp', + 'sprout/predef/platform/windows_desktop.hpp', + 'sprout/predef/platform/windows_phone.hpp', + 'sprout/predef/platform/windows_runtime.hpp', + 'sprout/predef/platform/windows_store.hpp', + 'sprout/predef/version_number.hpp', + 'sprout/preprocessor.hpp', + 'sprout/preprocessor/cat.hpp', + 'sprout/preprocessor/comma.hpp', + 'sprout/preprocessor/config.hpp', + 'sprout/preprocessor/empty.hpp', + 'sprout/preprocessor/some_number.hpp', + 'sprout/preprocessor/str.hpp', + 'sprout/preprocessor/str_all.hpp', + 'sprout/preprocessor/stringize.hpp', + 'sprout/preprocessor/stringize_all.hpp', + 'sprout/preprocessor/u16str.hpp', + 'sprout/preprocessor/u16stringize.hpp', + 'sprout/preprocessor/u32str.hpp', + 'sprout/preprocessor/u32stringize.hpp', + 'sprout/preprocessor/unique_string.hpp', + 'sprout/preprocessor/variadic.hpp', + 'sprout/preprocessor/variadic/elem.hpp', + 'sprout/preprocessor/variadic/size.hpp', + 'sprout/preprocessor/wstr.hpp', + 'sprout/preprocessor/wstringize.hpp', + 'sprout/random.hpp', + 'sprout/random/additive_combine.hpp', + 'sprout/random/bernoulli_distribution.hpp', + 'sprout/random/binomial_distribution.hpp', + 'sprout/random/default_random_engine.hpp', + 'sprout/random/detail/const_mod.hpp', + 'sprout/random/detail/generator_bits.hpp', + 'sprout/random/detail/ptr_helper.hpp', + 'sprout/random/detail/seed_impl.hpp', + 'sprout/random/detail/signed_unsigned_tools.hpp', + 'sprout/random/detail/uniform_int_float.hpp', + 'sprout/random/distribution.hpp', + 'sprout/random/engine.hpp', + 'sprout/random/generate_array.hpp', + 'sprout/random/generate_canonical.hpp', + 'sprout/random/geometric_distribution.hpp', + 'sprout/random/inversive_congruential.hpp', + 'sprout/random/iterator.hpp', + 'sprout/random/linear_congruential.hpp', + 'sprout/random/linear_feedback_shift.hpp', + 'sprout/random/mersenne_twister.hpp', + 'sprout/random/normal_distribution.hpp', + 'sprout/random/poisson_distribution.hpp', + 'sprout/random/random_result.hpp', + 'sprout/random/random_result_fwd.hpp', + 'sprout/random/range.hpp', + 'sprout/random/results.hpp', + 'sprout/random/seed.hpp', + 'sprout/random/seed_array.hpp', + 'sprout/random/shuffle_order.hpp', + 'sprout/random/taus88.hpp', + 'sprout/random/type_traits.hpp', + 'sprout/random/uniform_01.hpp', + 'sprout/random/uniform_int_distribution.hpp', + 'sprout/random/uniform_real_distribution.hpp', + 'sprout/random/uniform_smallint.hpp', + 'sprout/random/unique_seed.hpp', + 'sprout/random/utility.hpp', + 'sprout/random/variate_generator.hpp', + 'sprout/random/xor_combine.hpp', + 'sprout/range.hpp', + 'sprout/range/adaptor.hpp', + 'sprout/range/adaptor/adapted_dropped.hpp', + 'sprout/range/adaptor/adapted_dropped_end.hpp', + 'sprout/range/adaptor/adapted_offset.hpp', + 'sprout/range/adaptor/adapted_taken.hpp', + 'sprout/range/adaptor/adapted_taken_end.hpp', + 'sprout/range/adaptor/adapted_window.hpp', + 'sprout/range/adaptor/adjacent_filtered.hpp', + 'sprout/range/adaptor/alternated.hpp', + 'sprout/range/adaptor/amplitude_spectrum.hpp', + 'sprout/range/adaptor/blanked.hpp', + 'sprout/range/adaptor/clamped.hpp', + 'sprout/range/adaptor/copied.hpp', + 'sprout/range/adaptor/counting.hpp', + 'sprout/range/adaptor/deep_copied.hpp', + 'sprout/range/adaptor/detail/adapted_range_default.hpp', + 'sprout/range/adaptor/detail/jointed_range_default.hpp', + 'sprout/range/adaptor/detail/sized_range_default.hpp', + 'sprout/range/adaptor/dft.hpp', + 'sprout/range/adaptor/dropped.hpp', + 'sprout/range/adaptor/dropped_end.hpp', + 'sprout/range/adaptor/filled.hpp', + 'sprout/range/adaptor/filtered.hpp', + 'sprout/range/adaptor/idft.hpp', + 'sprout/range/adaptor/indexed.hpp', + 'sprout/range/adaptor/jointed.hpp', + 'sprout/range/adaptor/merged.hpp', + 'sprout/range/adaptor/modifying.hpp', + 'sprout/range/adaptor/moved.hpp', + 'sprout/range/adaptor/offset.hpp', + 'sprout/range/adaptor/outdirected.hpp', + 'sprout/range/adaptor/phase_spectrum.hpp', + 'sprout/range/adaptor/piped.hpp', + 'sprout/range/adaptor/reduction.hpp', + 'sprout/range/adaptor/removed.hpp', + 'sprout/range/adaptor/removed_if.hpp', + 'sprout/range/adaptor/replaced.hpp', + 'sprout/range/adaptor/replaced_if.hpp', + 'sprout/range/adaptor/reversed.hpp', + 'sprout/range/adaptor/sawtooth_wave.hpp', + 'sprout/range/adaptor/set_difference.hpp', + 'sprout/range/adaptor/set_intersection.hpp', + 'sprout/range/adaptor/set_symmetric_difference.hpp', + 'sprout/range/adaptor/set_union.hpp', + 'sprout/range/adaptor/sinusoidal.hpp', + 'sprout/range/adaptor/size_enumed.hpp', + 'sprout/range/adaptor/sized.hpp', + 'sprout/range/adaptor/square_wave.hpp', + 'sprout/range/adaptor/steps.hpp', + 'sprout/range/adaptor/string.hpp', + 'sprout/range/adaptor/taken.hpp', + 'sprout/range/adaptor/taken_end.hpp', + 'sprout/range/adaptor/to_lower.hpp', + 'sprout/range/adaptor/to_upper.hpp', + 'sprout/range/adaptor/transformed.hpp', + 'sprout/range/adaptor/triangle_wave.hpp', + 'sprout/range/adaptor/uniqued.hpp', + 'sprout/range/adaptor/valued.hpp', + 'sprout/range/adaptor/various.hpp', + 'sprout/range/adaptor/wave.hpp', + 'sprout/range/adaptor/window.hpp', + 'sprout/range/algorithm.hpp', + 'sprout/range/algorithm/adjacent_find.hpp', + 'sprout/range/algorithm/all_of.hpp', + 'sprout/range/algorithm/all_of_equal.hpp', + 'sprout/range/algorithm/any_of.hpp', + 'sprout/range/algorithm/any_of_equal.hpp', + 'sprout/range/algorithm/binary_search.hpp', + 'sprout/range/algorithm/bogo_sort.hpp', + 'sprout/range/algorithm/bozo_sort.hpp', + 'sprout/range/algorithm/clamp_range.hpp', + 'sprout/range/algorithm/clamp_range_copy.hpp', + 'sprout/range/algorithm/copy.hpp', + 'sprout/range/algorithm/copy_backward.hpp', + 'sprout/range/algorithm/copy_if.hpp', + 'sprout/range/algorithm/copy_until.hpp', + 'sprout/range/algorithm/copy_while.hpp', + 'sprout/range/algorithm/count.hpp', + 'sprout/range/algorithm/count_if.hpp', + 'sprout/range/algorithm/cxx14.hpp', + 'sprout/range/algorithm/cxx14/bogo_sort.hpp', + 'sprout/range/algorithm/cxx14/bozo_sort.hpp', + 'sprout/range/algorithm/cxx14/clamp_range.hpp', + 'sprout/range/algorithm/cxx14/copy.hpp', + 'sprout/range/algorithm/cxx14/copy_backward.hpp', + 'sprout/range/algorithm/cxx14/copy_if.hpp', + 'sprout/range/algorithm/cxx14/copy_until.hpp', + 'sprout/range/algorithm/cxx14/copy_while.hpp', + 'sprout/range/algorithm/cxx14/fill.hpp', + 'sprout/range/algorithm/cxx14/for_each.hpp', + 'sprout/range/algorithm/cxx14/gather.hpp', + 'sprout/range/algorithm/cxx14/generate.hpp', + 'sprout/range/algorithm/cxx14/inplace_merge.hpp', + 'sprout/range/algorithm/cxx14/make_heap.hpp', + 'sprout/range/algorithm/cxx14/merge.hpp', + 'sprout/range/algorithm/cxx14/move.hpp', + 'sprout/range/algorithm/cxx14/move_backward.hpp', + 'sprout/range/algorithm/cxx14/next_permutation.hpp', + 'sprout/range/algorithm/cxx14/nth_element.hpp', + 'sprout/range/algorithm/cxx14/partial_sort.hpp', + 'sprout/range/algorithm/cxx14/partial_sort_copy.hpp', + 'sprout/range/algorithm/cxx14/partition.hpp', + 'sprout/range/algorithm/cxx14/partition_copy.hpp', + 'sprout/range/algorithm/cxx14/pop_heap.hpp', + 'sprout/range/algorithm/cxx14/prev_permutation.hpp', + 'sprout/range/algorithm/cxx14/push_heap.hpp', + 'sprout/range/algorithm/cxx14/random_shuffle.hpp', + 'sprout/range/algorithm/cxx14/random_swap.hpp', + 'sprout/range/algorithm/cxx14/remove.hpp', + 'sprout/range/algorithm/cxx14/remove_copy.hpp', + 'sprout/range/algorithm/cxx14/remove_copy_if.hpp', + 'sprout/range/algorithm/cxx14/remove_if.hpp', + 'sprout/range/algorithm/cxx14/replace.hpp', + 'sprout/range/algorithm/cxx14/replace_copy.hpp', + 'sprout/range/algorithm/cxx14/replace_copy_if.hpp', + 'sprout/range/algorithm/cxx14/replace_if.hpp', + 'sprout/range/algorithm/cxx14/reverse.hpp', + 'sprout/range/algorithm/cxx14/reverse_copy.hpp', + 'sprout/range/algorithm/cxx14/rotate.hpp', + 'sprout/range/algorithm/cxx14/rotate_copy.hpp', + 'sprout/range/algorithm/cxx14/sample.hpp', + 'sprout/range/algorithm/cxx14/set_difference.hpp', + 'sprout/range/algorithm/cxx14/set_intersection.hpp', + 'sprout/range/algorithm/cxx14/set_symmetric_difference.hpp', + 'sprout/range/algorithm/cxx14/set_union.hpp', + 'sprout/range/algorithm/cxx14/shuffle.hpp', + 'sprout/range/algorithm/cxx14/sort.hpp', + 'sprout/range/algorithm/cxx14/sort_heap.hpp', + 'sprout/range/algorithm/cxx14/stable_partition.hpp', + 'sprout/range/algorithm/cxx14/stable_sort.hpp', + 'sprout/range/algorithm/cxx14/swap_ranges.hpp', + 'sprout/range/algorithm/cxx14/transform.hpp', + 'sprout/range/algorithm/cxx14/unique.hpp', + 'sprout/range/algorithm/cxx14/unique_copy.hpp', + 'sprout/range/algorithm/equal.hpp', + 'sprout/range/algorithm/equal_range.hpp', + 'sprout/range/algorithm/fill.hpp', + 'sprout/range/algorithm/find.hpp', + 'sprout/range/algorithm/find_difference.hpp', + 'sprout/range/algorithm/find_end.hpp', + 'sprout/range/algorithm/find_first_of.hpp', + 'sprout/range/algorithm/find_if.hpp', + 'sprout/range/algorithm/find_if_not.hpp', + 'sprout/range/algorithm/find_intersection.hpp', + 'sprout/range/algorithm/find_symmetric_difference.hpp', + 'sprout/range/algorithm/fit.hpp', + 'sprout/range/algorithm/fit/clamp_range_copy.hpp', + 'sprout/range/algorithm/fit/copy.hpp', + 'sprout/range/algorithm/fit/copy_backward.hpp', + 'sprout/range/algorithm/fit/copy_if.hpp', + 'sprout/range/algorithm/fit/copy_until.hpp', + 'sprout/range/algorithm/fit/copy_while.hpp', + 'sprout/range/algorithm/fit/merge.hpp', + 'sprout/range/algorithm/fit/partition_copy.hpp', + 'sprout/range/algorithm/fit/remove_copy.hpp', + 'sprout/range/algorithm/fit/remove_copy_if.hpp', + 'sprout/range/algorithm/fit/replace_copy.hpp', + 'sprout/range/algorithm/fit/replace_copy_if.hpp', + 'sprout/range/algorithm/fit/reverse_copy.hpp', + 'sprout/range/algorithm/fit/rotate_copy.hpp', + 'sprout/range/algorithm/fit/set_difference.hpp', + 'sprout/range/algorithm/fit/set_intersection.hpp', + 'sprout/range/algorithm/fit/set_symmetric_difference.hpp', + 'sprout/range/algorithm/fit/set_union.hpp', + 'sprout/range/algorithm/fit/stable_partition_copy.hpp', + 'sprout/range/algorithm/fit/swap_element_copy.hpp', + 'sprout/range/algorithm/fit/transform.hpp', + 'sprout/range/algorithm/fit/unique_copy.hpp', + 'sprout/range/algorithm/fixed.hpp', + 'sprout/range/algorithm/fixed/clamp_range_copy.hpp', + 'sprout/range/algorithm/fixed/copy.hpp', + 'sprout/range/algorithm/fixed/copy_backward.hpp', + 'sprout/range/algorithm/fixed/copy_if.hpp', + 'sprout/range/algorithm/fixed/copy_until.hpp', + 'sprout/range/algorithm/fixed/copy_while.hpp', + 'sprout/range/algorithm/fixed/merge.hpp', + 'sprout/range/algorithm/fixed/partition_copy.hpp', + 'sprout/range/algorithm/fixed/remove_copy.hpp', + 'sprout/range/algorithm/fixed/remove_copy_if.hpp', + 'sprout/range/algorithm/fixed/replace_copy.hpp', + 'sprout/range/algorithm/fixed/replace_copy_if.hpp', + 'sprout/range/algorithm/fixed/reverse_copy.hpp', + 'sprout/range/algorithm/fixed/rotate_copy.hpp', + 'sprout/range/algorithm/fixed/set_difference.hpp', + 'sprout/range/algorithm/fixed/set_intersection.hpp', + 'sprout/range/algorithm/fixed/set_symmetric_difference.hpp', + 'sprout/range/algorithm/fixed/set_union.hpp', + 'sprout/range/algorithm/fixed/stable_partition_copy.hpp', + 'sprout/range/algorithm/fixed/swap_element_copy.hpp', + 'sprout/range/algorithm/fixed/transform.hpp', + 'sprout/range/algorithm/fixed/unique_copy.hpp', + 'sprout/range/algorithm/generate.hpp', + 'sprout/range/algorithm/includes.hpp', + 'sprout/range/algorithm/inplace_merge.hpp', + 'sprout/range/algorithm/is_decreasing.hpp', + 'sprout/range/algorithm/is_heap.hpp', + 'sprout/range/algorithm/is_heap_until.hpp', + 'sprout/range/algorithm/is_increasing.hpp', + 'sprout/range/algorithm/is_partitioned.hpp', + 'sprout/range/algorithm/is_permutation.hpp', + 'sprout/range/algorithm/is_sorted.hpp', + 'sprout/range/algorithm/is_sorted_until.hpp', + 'sprout/range/algorithm/is_strictly_decreasing.hpp', + 'sprout/range/algorithm/is_strictly_increasing.hpp', + 'sprout/range/algorithm/lexicographical_compare.hpp', + 'sprout/range/algorithm/lower_bound.hpp', + 'sprout/range/algorithm/make_heap.hpp', + 'sprout/range/algorithm/max_element.hpp', + 'sprout/range/algorithm/merge.hpp', + 'sprout/range/algorithm/min_element.hpp', + 'sprout/range/algorithm/minmax_element.hpp', + 'sprout/range/algorithm/mismatch.hpp', + 'sprout/range/algorithm/modifying.hpp', + 'sprout/range/algorithm/move.hpp', + 'sprout/range/algorithm/move_backward.hpp', + 'sprout/range/algorithm/next_difference.hpp', + 'sprout/range/algorithm/next_intersection.hpp', + 'sprout/range/algorithm/next_permutation.hpp', + 'sprout/range/algorithm/next_symmetric_difference.hpp', + 'sprout/range/algorithm/next_union.hpp', + 'sprout/range/algorithm/non_modifying.hpp', + 'sprout/range/algorithm/none_of.hpp', + 'sprout/range/algorithm/none_of_equal.hpp', + 'sprout/range/algorithm/nth_element.hpp', + 'sprout/range/algorithm/one_of.hpp', + 'sprout/range/algorithm/one_of_equal.hpp', + 'sprout/range/algorithm/partial_sort.hpp', + 'sprout/range/algorithm/partial_sort_copy.hpp', + 'sprout/range/algorithm/partition.hpp', + 'sprout/range/algorithm/partition_copy.hpp', + 'sprout/range/algorithm/partition_point.hpp', + 'sprout/range/algorithm/pop_heap.hpp', + 'sprout/range/algorithm/prev_permutation.hpp', + 'sprout/range/algorithm/push_heap.hpp', + 'sprout/range/algorithm/random_shuffle.hpp', + 'sprout/range/algorithm/random_swap.hpp', + 'sprout/range/algorithm/remove.hpp', + 'sprout/range/algorithm/remove_copy.hpp', + 'sprout/range/algorithm/remove_copy_if.hpp', + 'sprout/range/algorithm/remove_if.hpp', + 'sprout/range/algorithm/replace.hpp', + 'sprout/range/algorithm/replace_copy.hpp', + 'sprout/range/algorithm/replace_copy_if.hpp', + 'sprout/range/algorithm/replace_if.hpp', + 'sprout/range/algorithm/reverse.hpp', + 'sprout/range/algorithm/reverse_copy.hpp', + 'sprout/range/algorithm/rotate.hpp', + 'sprout/range/algorithm/rotate_copy.hpp', + 'sprout/range/algorithm/sample.hpp', + 'sprout/range/algorithm/search.hpp', + 'sprout/range/algorithm/search_n.hpp', + 'sprout/range/algorithm/set_difference.hpp', + 'sprout/range/algorithm/set_intersection.hpp', + 'sprout/range/algorithm/set_symmetric_difference.hpp', + 'sprout/range/algorithm/set_union.hpp', + 'sprout/range/algorithm/shuffle.hpp', + 'sprout/range/algorithm/sort.hpp', + 'sprout/range/algorithm/sort_heap.hpp', + 'sprout/range/algorithm/stable_partition.hpp', + 'sprout/range/algorithm/stable_partition_copy.hpp', + 'sprout/range/algorithm/stable_sort.hpp', + 'sprout/range/algorithm/string.hpp', + 'sprout/range/algorithm/string/case_conv.hpp', + 'sprout/range/algorithm/string/fit/case_conv.hpp', + 'sprout/range/algorithm/string/fit/to_lower_copy.hpp', + 'sprout/range/algorithm/string/fit/to_upper_copy.hpp', + 'sprout/range/algorithm/string/fixed/case_conv.hpp', + 'sprout/range/algorithm/string/fixed/to_lower_copy.hpp', + 'sprout/range/algorithm/string/fixed/to_upper_copy.hpp', + 'sprout/range/algorithm/string/to_lower_copy.hpp', + 'sprout/range/algorithm/string/to_upper_copy.hpp', + 'sprout/range/algorithm/swap_element_copy.hpp', + 'sprout/range/algorithm/swap_ranges.hpp', + 'sprout/range/algorithm/transform.hpp', + 'sprout/range/algorithm/tristate_lexicographical_compare.hpp', + 'sprout/range/algorithm/unique.hpp', + 'sprout/range/algorithm/unique_copy.hpp', + 'sprout/range/algorithm/upper_bound.hpp', + 'sprout/range/numeric.hpp', + 'sprout/range/numeric/accumulate.hpp', + 'sprout/range/numeric/adjacent_difference.hpp', + 'sprout/range/numeric/cxx14.hpp', + 'sprout/range/numeric/cxx14/adjacent_difference.hpp', + 'sprout/range/numeric/cxx14/exclusive_scan.hpp', + 'sprout/range/numeric/cxx14/inclusive_scan.hpp', + 'sprout/range/numeric/cxx14/iota.hpp', + 'sprout/range/numeric/cxx14/partial_sum.hpp', + 'sprout/range/numeric/cxx14/transform_exclusive_scan.hpp', + 'sprout/range/numeric/cxx14/transform_inclusive_scan.hpp', + 'sprout/range/numeric/dft.hpp', + 'sprout/range/numeric/dft/amplitude_spectrum.hpp', + 'sprout/range/numeric/dft/cxx14.hpp', + 'sprout/range/numeric/dft/cxx14/amplitude_spectrum.hpp', + 'sprout/range/numeric/dft/cxx14/phase_spectrum.hpp', + 'sprout/range/numeric/dft/cxx14/sawtooth.hpp', + 'sprout/range/numeric/dft/cxx14/sinusoid.hpp', + 'sprout/range/numeric/dft/cxx14/spectrum.hpp', + 'sprout/range/numeric/dft/cxx14/square.hpp', + 'sprout/range/numeric/dft/cxx14/triangle.hpp', + 'sprout/range/numeric/dft/cxx14/wave.hpp', + 'sprout/range/numeric/dft/dft.hpp', + 'sprout/range/numeric/dft/dft_element.hpp', + 'sprout/range/numeric/dft/fit.hpp', + 'sprout/range/numeric/dft/fit/amplitude_spectrum.hpp', + 'sprout/range/numeric/dft/fit/dft.hpp', + 'sprout/range/numeric/dft/fit/idft.hpp', + 'sprout/range/numeric/dft/fit/phase_spectrum.hpp', + 'sprout/range/numeric/dft/fit/spectrum.hpp', + 'sprout/range/numeric/dft/fixed.hpp', + 'sprout/range/numeric/dft/fixed/amplitude_spectrum.hpp', + 'sprout/range/numeric/dft/fixed/dft.hpp', + 'sprout/range/numeric/dft/fixed/idft.hpp', + 'sprout/range/numeric/dft/fixed/phase_spectrum.hpp', + 'sprout/range/numeric/dft/fixed/spectrum.hpp', + 'sprout/range/numeric/dft/idft.hpp', + 'sprout/range/numeric/dft/idft_element.hpp', + 'sprout/range/numeric/dft/modifying.hpp', + 'sprout/range/numeric/dft/non_modifying.hpp', + 'sprout/range/numeric/dft/phase_spectrum.hpp', + 'sprout/range/numeric/dft/spectrum.hpp', + 'sprout/range/numeric/exclusive_scan.hpp', + 'sprout/range/numeric/fft.hpp', + 'sprout/range/numeric/fft/fft.hpp', + 'sprout/range/numeric/fft/ifft.hpp', + 'sprout/range/numeric/fit.hpp', + 'sprout/range/numeric/fit/adjacent_difference.hpp', + 'sprout/range/numeric/fit/exclusive_scan.hpp', + 'sprout/range/numeric/fit/inclusive_scan.hpp', + 'sprout/range/numeric/fit/partial_sum.hpp', + 'sprout/range/numeric/fit/transform_exclusive_scan.hpp', + 'sprout/range/numeric/fit/transform_inclusive_scan.hpp', + 'sprout/range/numeric/fixed.hpp', + 'sprout/range/numeric/fixed/adjacent_difference.hpp', + 'sprout/range/numeric/fixed/exclusive_scan.hpp', + 'sprout/range/numeric/fixed/inclusive_scan.hpp', + 'sprout/range/numeric/fixed/partial_sum.hpp', + 'sprout/range/numeric/fixed/transform_exclusive_scan.hpp', + 'sprout/range/numeric/fixed/transform_inclusive_scan.hpp', + 'sprout/range/numeric/inclusive_scan.hpp', + 'sprout/range/numeric/inner_product.hpp', + 'sprout/range/numeric/modifying.hpp', + 'sprout/range/numeric/non_modifying.hpp', + 'sprout/range/numeric/partial_sum.hpp', + 'sprout/range/numeric/reduce.hpp', + 'sprout/range/numeric/transform_exclusive_scan.hpp', + 'sprout/range/numeric/transform_inclusive_scan.hpp', + 'sprout/range/numeric/transform_reduce.hpp', + 'sprout/range/ptr_range.hpp', + 'sprout/range/range.hpp', + 'sprout/range/range_container.hpp', + 'sprout/range/range_return.hpp', + 'sprout/range/type_traits.hpp', + 'sprout/range/type_traits/lvalue_iterator.hpp', + 'sprout/range/type_traits/lvalue_range.hpp', + 'sprout/rational.hpp', + 'sprout/rational/arithmetic.hpp', + 'sprout/rational/comparison.hpp', + 'sprout/rational/container.hpp', + 'sprout/rational/conversion.hpp', + 'sprout/rational/exceptions.hpp', + 'sprout/rational/hash.hpp', + 'sprout/rational/io.hpp', + 'sprout/rational/literals.hpp', + 'sprout/rational/rational.hpp', + 'sprout/rational/tuple.hpp', + 'sprout/rational/values.hpp', + 'sprout/sized_pit.hpp', + 'sprout/sized_pit/comparison.hpp', + 'sprout/sized_pit/container.hpp', + 'sprout/sized_pit/hash.hpp', + 'sprout/sized_pit/sized_pit.hpp', + 'sprout/sized_pit/tuple.hpp', + 'sprout/sized_pit/type_traits.hpp', + 'sprout/stateful.hpp', + 'sprout/stateful/counter.hpp', + 'sprout/stateful/rand.hpp', + 'sprout/stateful/type_index.hpp', + 'sprout/stateful/typed_counter.hpp', + 'sprout/stateful/typed_id.hpp', + 'sprout/stateful/typed_rand.hpp', + 'sprout/stateful/typed_slot.hpp', + 'sprout/static_assert.hpp', + 'sprout/static_warning.hpp', + 'sprout/string.hpp', + 'sprout/string/alias.hpp', + 'sprout/string/char_traits.hpp', + 'sprout/string/comparison.hpp', + 'sprout/string/concat.hpp', + 'sprout/string/container.hpp', + 'sprout/string/conversion.hpp', + 'sprout/string/detail/compare.hpp', + 'sprout/string/detail/find.hpp', + 'sprout/string/detail/operations.hpp', + 'sprout/string/float_to_string.hpp', + 'sprout/string/from_string.hpp', + 'sprout/string/hash.hpp', + 'sprout/string/int_to_string.hpp', + 'sprout/string/io.hpp', + 'sprout/string/make_string.hpp', + 'sprout/string/npos.hpp', + 'sprout/string/shift_concat.hpp', + 'sprout/string/shrink.hpp', + 'sprout/string/stretch.hpp', + 'sprout/string/string.hpp', + 'sprout/string/string_to_float.hpp', + 'sprout/string/string_to_int.hpp', + 'sprout/string/to_string.hpp', + 'sprout/string/to_string_array.hpp', + 'sprout/string/to_string_value.hpp', + 'sprout/string/tuple.hpp', + 'sprout/string/type_traits.hpp', + 'sprout/sub_array.hpp', + 'sprout/sub_array/array_sub.hpp', + 'sprout/sub_array/comparison.hpp', + 'sprout/sub_array/container.hpp', + 'sprout/sub_array/hash.hpp', + 'sprout/sub_array/sub.hpp', + 'sprout/sub_array/sub_array.hpp', + 'sprout/sub_array/sub_offset.hpp', + 'sprout/sub_array/sub_window.hpp', + 'sprout/sub_array/tuple.hpp', + 'sprout/sub_array/type_traits.hpp', + 'sprout/tpp/algorithm.hpp', + 'sprout/tpp/algorithm/all_of.hpp', + 'sprout/tpp/algorithm/any_of.hpp', + 'sprout/tpp/algorithm/max_element.hpp', + 'sprout/tpp/algorithm/min_element.hpp', + 'sprout/tpp/algorithm/none_of.hpp', + 'sprout/tpp/algorithm/one_of.hpp', + 'sprout/tuple.hpp', + 'sprout/tuple/algorithm.hpp', + 'sprout/tuple/algorithm/copy.hpp', + 'sprout/tuple/apply.hpp', + 'sprout/tuple/boost/array.hpp', + 'sprout/tuple/deep_copy.hpp', + 'sprout/tuple/default_construct.hpp', + 'sprout/tuple/flex.hpp', + 'sprout/tuple/flexibly_construct.hpp', + 'sprout/tuple/functions.hpp', + 'sprout/tuple/fused.hpp', + 'sprout/tuple/indexes.hpp', + 'sprout/tuple/make.hpp', + 'sprout/tuple/make_from_tuple.hpp', + 'sprout/tuple/metafunctions.hpp', + 'sprout/tuple/operation.hpp', + 'sprout/tuple/operation/append_back.hpp', + 'sprout/tuple/operation/append_front.hpp', + 'sprout/tuple/operation/pop_back.hpp', + 'sprout/tuple/operation/pop_front.hpp', + 'sprout/tuple/operation/push_back.hpp', + 'sprout/tuple/operation/push_front.hpp', + 'sprout/tuple/remake.hpp', + 'sprout/tuple/sscrisk/cel/array.hpp', + 'sprout/tuple/sscrisk/cel/utility.hpp', + 'sprout/tuple/std/array.hpp', + 'sprout/tuple/std/complex.hpp', + 'sprout/tuple/std/utility.hpp', + 'sprout/tuple/traits.hpp', + 'sprout/tuple/tuple.hpp', + 'sprout/tuple/tuple/comparison.hpp', + 'sprout/tuple/tuple/get.hpp', + 'sprout/tuple/tuple/has_sprout_get.hpp', + 'sprout/tuple/tuple/hash.hpp', + 'sprout/tuple/tuple/ignore.hpp', + 'sprout/tuple/tuple/make_tuple.hpp', + 'sprout/tuple/tuple/traits.hpp', + 'sprout/tuple/tuple/tuple.hpp', + 'sprout/tuple/tuple/tuple_access_traits.hpp', + 'sprout/tuple/tuple/tuple_decl.hpp', + 'sprout/tuple/tuple/tuple_element.hpp', + 'sprout/tuple/tuple/tuple_fwd.hpp', + 'sprout/tuple/tuple/tuple_size.hpp', + 'sprout/tuple/tuple/tuple_traits.hpp', + 'sprout/tuple/tuple/type_traits.hpp', + 'sprout/type.hpp', + 'sprout/type/algorithm.hpp', + 'sprout/type/algorithm/accumulate.hpp', + 'sprout/type/algorithm/all_of.hpp', + 'sprout/type/algorithm/all_of_same.hpp', + 'sprout/type/algorithm/any_of.hpp', + 'sprout/type/algorithm/any_of_same.hpp', + 'sprout/type/algorithm/contains.hpp', + 'sprout/type/algorithm/contains_if.hpp', + 'sprout/type/algorithm/count.hpp', + 'sprout/type/algorithm/count_if.hpp', + 'sprout/type/algorithm/detail/find_index_result.hpp', + 'sprout/type/algorithm/find_index.hpp', + 'sprout/type/algorithm/find_index_if.hpp', + 'sprout/type/algorithm/fold.hpp', + 'sprout/type/algorithm/lower_bound_index.hpp', + 'sprout/type/algorithm/none_of.hpp', + 'sprout/type/algorithm/none_of_same.hpp', + 'sprout/type/algorithm/one_of.hpp', + 'sprout/type/algorithm/one_of_same.hpp', + 'sprout/type/algorithm/partial_sum.hpp', + 'sprout/type/algorithm/transform.hpp', + 'sprout/type/algorithm/upper_bound_index.hpp', + 'sprout/type/apply.hpp', + 'sprout/type/boost/mpl/detail/tuple_element.hpp', + 'sprout/type/boost/mpl/string.hpp', + 'sprout/type/boost/mpl/v_iter.hpp', + 'sprout/type/boost/mpl/vector.hpp', + 'sprout/type/boost/mpl/vector_c.hpp', + 'sprout/type/functional.hpp', + 'sprout/type/functional/arithmetic.hpp', + 'sprout/type/functional/comparison.hpp', + 'sprout/type/functional/detail/arithmetic_op.hpp', + 'sprout/type/functional/detail/comparison_op.hpp', + 'sprout/type/functional/divides.hpp', + 'sprout/type/functional/equal_to.hpp', + 'sprout/type/functional/greater.hpp', + 'sprout/type/functional/greater_equal.hpp', + 'sprout/type/functional/less.hpp', + 'sprout/type/functional/less_equal.hpp', + 'sprout/type/functional/minus.hpp', + 'sprout/type/functional/modulus.hpp', + 'sprout/type/functional/multiplies.hpp', + 'sprout/type/functional/negate.hpp', + 'sprout/type/functional/not_equal_to.hpp', + 'sprout/type/functional/plus.hpp', + 'sprout/type/functional/posite.hpp', + 'sprout/type/integral_array.hpp', + 'sprout/type/iterator.hpp', + 'sprout/type/iterator/advance.hpp', + 'sprout/type/iterator/deref.hpp', + 'sprout/type/iterator/distance.hpp', + 'sprout/type/iterator/index_iterator.hpp', + 'sprout/type/iterator/next.hpp', + 'sprout/type/iterator/prev.hpp', + 'sprout/type/joint_types.hpp', + 'sprout/type/map_types.hpp', + 'sprout/type/operation.hpp', + 'sprout/type/operation/append_back.hpp', + 'sprout/type/operation/append_front.hpp', + 'sprout/type/operation/assign.hpp', + 'sprout/type/operation/at.hpp', + 'sprout/type/operation/back.hpp', + 'sprout/type/operation/empty.hpp', + 'sprout/type/operation/front.hpp', + 'sprout/type/operation/map.hpp', + 'sprout/type/operation/pop_back.hpp', + 'sprout/type/operation/pop_front.hpp', + 'sprout/type/operation/push_back.hpp', + 'sprout/type/operation/push_front.hpp', + 'sprout/type/operation/rebind.hpp', + 'sprout/type/operation/size.hpp', + 'sprout/type/operation/tuple_cat.hpp', + 'sprout/type/packer.hpp', + 'sprout/type/pop_front_types.hpp', + 'sprout/type/print.hpp', + 'sprout/type/quote.hpp', + 'sprout/type/rebind_types.hpp', + 'sprout/type/self.hpp', + 'sprout/type/seq/algorithm.hpp', + 'sprout/type/seq/algorithm/find.hpp', + 'sprout/type/seq/algorithm/find_if.hpp', + 'sprout/type/string.hpp', + 'sprout/type/string/alias.hpp', + 'sprout/type/string/string.hpp', + 'sprout/type/string/to_string.hpp', + 'sprout/type/string/to_string_constant.hpp', + 'sprout/type/tuple.hpp', + 'sprout/type/type_tuple.hpp', + 'sprout/type/type_tuple_decl.hpp', + 'sprout/type/uniform_types.hpp', + 'sprout/type/void.hpp', + 'sprout/type_traits.hpp', + 'sprout/type_traits/add_const.hpp', + 'sprout/type_traits/add_cv.hpp', + 'sprout/type_traits/add_lvalue_reference.hpp', + 'sprout/type_traits/add_pointer.hpp', + 'sprout/type_traits/add_rvalue_reference.hpp', + 'sprout/type_traits/add_volatile.hpp', + 'sprout/type_traits/aligned_storage.hpp', + 'sprout/type_traits/aligned_union.hpp', + 'sprout/type_traits/alignment_of.hpp', + 'sprout/type_traits/arithmetic_promote.hpp', + 'sprout/type_traits/array_modification.hpp', + 'sprout/type_traits/category.hpp', + 'sprout/type_traits/common_decay.hpp', + 'sprout/type_traits/common_type.hpp', + 'sprout/type_traits/complex_promote.hpp', + 'sprout/type_traits/composite_category.hpp', + 'sprout/type_traits/composite_modification.hpp', + 'sprout/type_traits/conditional.hpp', + 'sprout/type_traits/conjunction.hpp', + 'sprout/type_traits/const_reference.hpp', + 'sprout/type_traits/copy_const.hpp', + 'sprout/type_traits/copy_cv.hpp', + 'sprout/type_traits/copy_volatile.hpp', + 'sprout/type_traits/cv_modification.hpp', + 'sprout/type_traits/decay.hpp', + 'sprout/type_traits/detail/has_binary_op.hpp', + 'sprout/type_traits/detail/has_post_unary_op.hpp', + 'sprout/type_traits/detail/has_pre_unary_op.hpp', + 'sprout/type_traits/detail/has_subscript_op.hpp', + 'sprout/type_traits/detail/invoke.hpp', + 'sprout/type_traits/detail/type_traits_wrapper.hpp', + 'sprout/type_traits/disjunction.hpp', + 'sprout/type_traits/dont_care.hpp', + 'sprout/type_traits/enable_if.hpp', + 'sprout/type_traits/enable_if_has_type.hpp', + 'sprout/type_traits/enabler_if.hpp', + 'sprout/type_traits/extent.hpp', + 'sprout/type_traits/float_promote.hpp', + 'sprout/type_traits/has_address_of.hpp', + 'sprout/type_traits/has_arithmetic_operator.hpp', + 'sprout/type_traits/has_assign.hpp', + 'sprout/type_traits/has_assignment_operator.hpp', + 'sprout/type_traits/has_bit_and.hpp', + 'sprout/type_traits/has_bit_and_assign.hpp', + 'sprout/type_traits/has_bit_not.hpp', + 'sprout/type_traits/has_bit_or.hpp', + 'sprout/type_traits/has_bit_or_assign.hpp', + 'sprout/type_traits/has_bit_xor.hpp', + 'sprout/type_traits/has_bit_xor_assign.hpp', + 'sprout/type_traits/has_bitwise_operator.hpp', + 'sprout/type_traits/has_comma.hpp', + 'sprout/type_traits/has_comparison_operator.hpp', + 'sprout/type_traits/has_complement.hpp', + 'sprout/type_traits/has_dereference.hpp', + 'sprout/type_traits/has_divides.hpp', + 'sprout/type_traits/has_divides_assign.hpp', + 'sprout/type_traits/has_equal_to.hpp', + 'sprout/type_traits/has_greater.hpp', + 'sprout/type_traits/has_greater_equal.hpp', + 'sprout/type_traits/has_inc_dec_operator.hpp', + 'sprout/type_traits/has_left_shift.hpp', + 'sprout/type_traits/has_left_shift_assign.hpp', + 'sprout/type_traits/has_less.hpp', + 'sprout/type_traits/has_less_equal.hpp', + 'sprout/type_traits/has_logical_and.hpp', + 'sprout/type_traits/has_logical_not.hpp', + 'sprout/type_traits/has_logical_operator.hpp', + 'sprout/type_traits/has_logical_or.hpp', + 'sprout/type_traits/has_member.hpp', + 'sprout/type_traits/has_member_pointer.hpp', + 'sprout/type_traits/has_members_operator.hpp', + 'sprout/type_traits/has_minus.hpp', + 'sprout/type_traits/has_minus_assign.hpp', + 'sprout/type_traits/has_modulus.hpp', + 'sprout/type_traits/has_modulus_assign.hpp', + 'sprout/type_traits/has_multiplies.hpp', + 'sprout/type_traits/has_multiplies_assign.hpp', + 'sprout/type_traits/has_negate.hpp', + 'sprout/type_traits/has_not_equal_to.hpp', + 'sprout/type_traits/has_operator.hpp', + 'sprout/type_traits/has_plus.hpp', + 'sprout/type_traits/has_plus_assign.hpp', + 'sprout/type_traits/has_posite.hpp', + 'sprout/type_traits/has_post_decrement.hpp', + 'sprout/type_traits/has_post_increment.hpp', + 'sprout/type_traits/has_pre_decrement.hpp', + 'sprout/type_traits/has_pre_increment.hpp', + 'sprout/type_traits/has_reference_operator.hpp', + 'sprout/type_traits/has_right_shift.hpp', + 'sprout/type_traits/has_right_shift_assign.hpp', + 'sprout/type_traits/has_shift_left.hpp', + 'sprout/type_traits/has_shift_left_assign.hpp', + 'sprout/type_traits/has_shift_right.hpp', + 'sprout/type_traits/has_shift_right_assign.hpp', + 'sprout/type_traits/has_subscript.hpp', + 'sprout/type_traits/has_type.hpp', + 'sprout/type_traits/has_unary_minus.hpp', + 'sprout/type_traits/has_unary_plus.hpp', + 'sprout/type_traits/has_unique_object_representations.hpp', + 'sprout/type_traits/has_value.hpp', + 'sprout/type_traits/has_various_operator.hpp', + 'sprout/type_traits/has_virtual_destructor.hpp', + 'sprout/type_traits/has_xxx.hpp', + 'sprout/type_traits/identity.hpp', + 'sprout/type_traits/inherit_if_type.hpp', + 'sprout/type_traits/inherit_if_xxx.hpp', + 'sprout/type_traits/integral_constant.hpp', + 'sprout/type_traits/introspection.hpp', + 'sprout/type_traits/invoke_result.hpp', + 'sprout/type_traits/is_abstract.hpp', + 'sprout/type_traits/is_aggregate.hpp', + 'sprout/type_traits/is_arithmetic.hpp', + 'sprout/type_traits/is_array.hpp', + 'sprout/type_traits/is_assignable.hpp', + 'sprout/type_traits/is_base_of.hpp', + 'sprout/type_traits/is_c_str.hpp', + 'sprout/type_traits/is_char_type.hpp', + 'sprout/type_traits/is_class.hpp', + 'sprout/type_traits/is_compound.hpp', + 'sprout/type_traits/is_const.hpp', + 'sprout/type_traits/is_const_cast_convertible.hpp', + 'sprout/type_traits/is_const_unqualified.hpp', + 'sprout/type_traits/is_constructible.hpp', + 'sprout/type_traits/is_convert_constructible.hpp', + 'sprout/type_traits/is_convertible.hpp', + 'sprout/type_traits/is_copy_assignable.hpp', + 'sprout/type_traits/is_copy_constructible.hpp', + 'sprout/type_traits/is_cv_unqualified.hpp', + 'sprout/type_traits/is_default_constructible.hpp', + 'sprout/type_traits/is_destructible.hpp', + 'sprout/type_traits/is_empty.hpp', + 'sprout/type_traits/is_enum.hpp', + 'sprout/type_traits/is_final.hpp', + 'sprout/type_traits/is_floating_point.hpp', + 'sprout/type_traits/is_function.hpp', + 'sprout/type_traits/is_fundamental.hpp', + 'sprout/type_traits/is_integral.hpp', + 'sprout/type_traits/is_invocable.hpp', + 'sprout/type_traits/is_invocable_r.hpp', + 'sprout/type_traits/is_literal_type.hpp', + 'sprout/type_traits/is_lvalue_reference.hpp', + 'sprout/type_traits/is_member_function_pointer.hpp', + 'sprout/type_traits/is_member_object_pointer.hpp', + 'sprout/type_traits/is_member_pointer.hpp', + 'sprout/type_traits/is_move_assignable.hpp', + 'sprout/type_traits/is_move_constructible.hpp', + 'sprout/type_traits/is_nothrow_assignable.hpp', + 'sprout/type_traits/is_nothrow_constructible.hpp', + 'sprout/type_traits/is_nothrow_copy_assignable.hpp', + 'sprout/type_traits/is_nothrow_copy_constructible.hpp', + 'sprout/type_traits/is_nothrow_default_constructible.hpp', + 'sprout/type_traits/is_nothrow_destructible.hpp', + 'sprout/type_traits/is_nothrow_invocable.hpp', + 'sprout/type_traits/is_nothrow_invocable_r.hpp', + 'sprout/type_traits/is_nothrow_move_assignable.hpp', + 'sprout/type_traits/is_object.hpp', + 'sprout/type_traits/is_nothrow_move_constructible.hpp', + 'sprout/type_traits/is_null_pointer.hpp', + 'sprout/type_traits/is_pointer.hpp', + 'sprout/type_traits/is_reference.hpp', + 'sprout/type_traits/is_rvalue_reference.hpp', + 'sprout/type_traits/is_sint.hpp', + 'sprout/type_traits/is_swappable_with.hpp', + 'sprout/type_traits/is_trivially_assignable.hpp', + 'sprout/type_traits/is_trivially_copy_constructible.hpp', + 'sprout/type_traits/is_trivially_default_constructible.hpp', + 'sprout/type_traits/is_trivially_destructible.hpp', + 'sprout/type_traits/is_trivially_move_assignable.hpp', + 'sprout/type_traits/is_unsigned.hpp', + 'sprout/type_traits/is_void.hpp', + 'sprout/type_traits/logical.hpp', + 'sprout/type_traits/lvalue_reference.hpp', + 'sprout/type_traits/make_unsigned.hpp', + 'sprout/type_traits/negation.hpp', + 'sprout/type_traits/pointer_modification.hpp', + 'sprout/type_traits/property.hpp', + 'sprout/type_traits/remove_cvref.hpp', + 'sprout/type_traits/remove_pointer.hpp', + 'sprout/type_traits/remove_reference.hpp', + 'sprout/type_traits/remove_shallow_const.hpp', + 'sprout/type_traits/remove_shallow_cv.hpp', + 'sprout/type_traits/remove_shallow_cvref.hpp', + 'sprout/type_traits/remove_shallow_volatile.hpp', + 'sprout/type_traits/result_of.hpp', + 'sprout/type_traits/std.hpp', + 'sprout/type_traits/transformation.hpp', + 'sprout/type_traits/underlying_type.hpp', + 'sprout/type_traits/is_nothrow_swappable.hpp', + 'sprout/type_traits/is_nothrow_swappable_with.hpp', + 'sprout/type_traits/is_nullptr_cast.hpp', + 'sprout/type_traits/is_pod.hpp', + 'sprout/type_traits/is_polymorphic.hpp', + 'sprout/type_traits/is_same.hpp', + 'sprout/type_traits/is_scalar.hpp', + 'sprout/type_traits/is_signed.hpp', + 'sprout/type_traits/is_standard_layout.hpp', + 'sprout/type_traits/is_swappable.hpp', + 'sprout/type_traits/is_trivial.hpp', + 'sprout/type_traits/is_trivially_constructible.hpp', + 'sprout/type_traits/is_trivially_copy_assignable.hpp', + 'sprout/type_traits/is_trivially_copyable.hpp', + 'sprout/type_traits/is_trivially_move_constructible.hpp', + 'sprout/type_traits/is_uint.hpp', + 'sprout/type_traits/is_union.hpp', + 'sprout/type_traits/is_upcast.hpp', + 'sprout/type_traits/is_volatile.hpp', + 'sprout/type_traits/is_volatile_unqualified.hpp', + 'sprout/type_traits/is_within_namespace.hpp', + 'sprout/type_traits/is_within_namespace_boost.hpp', + 'sprout/type_traits/is_within_namespace_sprout.hpp', + 'sprout/type_traits/is_within_namespace_std.hpp', + 'sprout/type_traits/is_within_tag_namespace.hpp', + 'sprout/type_traits/make_signed.hpp', + 'sprout/type_traits/property_query.hpp', + 'sprout/type_traits/rank.hpp', + 'sprout/type_traits/ref_modification.hpp', + 'sprout/type_traits/relationship.hpp', + 'sprout/type_traits/remove_all_extents.hpp', + 'sprout/type_traits/remove_const.hpp', + 'sprout/type_traits/remove_cv.hpp', + 'sprout/type_traits/remove_extent.hpp', + 'sprout/type_traits/remove_volatile.hpp', + 'sprout/type_traits/sign_modification.hpp', + 'sprout/type_traits/std_type_aliases.hpp', + 'sprout/type_traits/std_type_traits.hpp', + 'sprout/type_traits/std_value_variables.hpp', + 'sprout/type_traits/void_t.hpp', + 'sprout/type_traits/voider.hpp', + 'sprout/utility.hpp', + 'sprout/utility/any_convertible.hpp', + 'sprout/utility/as_const.hpp', + 'sprout/utility/as_lvalue.hpp', + 'sprout/utility/as_non_const.hpp', + 'sprout/utility/cast.hpp', + 'sprout/utility/compare_pointees.hpp', + 'sprout/utility/comparison.hpp', + 'sprout/utility/dyn_cast.hpp', + 'sprout/utility/eat.hpp', + 'sprout/utility/enabler_if.hpp', + 'sprout/utility/exchange.hpp', + 'sprout/utility/fold.hpp', + 'sprout/utility/forward.hpp', + 'sprout/utility/ignore_unused.hpp', + 'sprout/utility/implicit_cast.hpp', + 'sprout/utility/limited.hpp', + 'sprout/utility/loop.hpp', + 'sprout/utility/lvalue_forward.hpp', + 'sprout/utility/move.hpp', + 'sprout/utility/noncopyable.hpp', + 'sprout/utility/operation.hpp', + 'sprout/utility/operation_ext.hpp', + 'sprout/utility/pack.hpp', + 'sprout/utility/pair.hpp', + 'sprout/utility/pair/access.hpp', + 'sprout/utility/pair/comparison.hpp', + 'sprout/utility/pair/first.hpp', + 'sprout/utility/pair/hash.hpp', + 'sprout/utility/pair/make_pair.hpp', + 'sprout/utility/pair/pair.hpp', + 'sprout/utility/pair/pair_decl.hpp', + 'sprout/utility/pair/pair_fwd.hpp', + 'sprout/utility/pair/second.hpp', + 'sprout/utility/pair/tuple.hpp', + 'sprout/utility/pass_through.hpp', + 'sprout/utility/reinter_cast.hpp', + 'sprout/utility/rel_ops.hpp', + 'sprout/utility/string_ref.hpp', + 'sprout/utility/string_view.hpp', + 'sprout/utility/string_view/alias.hpp', + 'sprout/utility/string_view/comparison.hpp', + 'sprout/utility/string_view/conversion.hpp', + 'sprout/utility/string_view/from_string.hpp', + 'sprout/utility/string_view/hash.hpp', + 'sprout/utility/string_view/io.hpp', + 'sprout/utility/string_view/literals.hpp', + 'sprout/utility/string_view/string_ref.hpp', + 'sprout/utility/string_view/string_to_float.hpp', + 'sprout/utility/string_view/string_to_int.hpp', + 'sprout/utility/string_view/string_view.hpp', + 'sprout/utility/string_view/string_view_fwd.hpp', + 'sprout/utility/string_view/type_traits.hpp', + 'sprout/utility/swallow.hpp', + 'sprout/utility/swap.hpp', + 'sprout/utility/unmove.hpp', + 'sprout/utility/until_loop.hpp', + 'sprout/utility/upcast.hpp', + 'sprout/utility/use_default.hpp', + 'sprout/utility/value_holder.hpp', + 'sprout/utility/value_holder/comparison.hpp', + 'sprout/utility/value_holder/get.hpp', + 'sprout/utility/value_holder/hash.hpp', + 'sprout/utility/value_holder/io.hpp', + 'sprout/utility/value_holder/value_holder.hpp', + 'sprout/utility/while_loop.hpp', + 'sprout/uuid.hpp', + 'sprout/uuid/detail/table.hpp', + 'sprout/uuid/generators.hpp', + 'sprout/uuid/hash.hpp', + 'sprout/uuid/io.hpp', + 'sprout/uuid/literals.hpp', + 'sprout/uuid/md5_name_generator.hpp', + 'sprout/uuid/name_generator.hpp', + 'sprout/uuid/namespaces.hpp', + 'sprout/uuid/nil_generator.hpp', + 'sprout/uuid/random_generator.hpp', + 'sprout/uuid/sha1_name_generator.hpp', + 'sprout/uuid/string_generator.hpp', + 'sprout/uuid/tuple.hpp', + 'sprout/uuid/uuid.hpp', + 'sprout/valarray.hpp', + 'sprout/valarray/arithmetic.hpp', + 'sprout/valarray/bitwise.hpp', + 'sprout/valarray/comparison.hpp', + 'sprout/valarray/container.hpp', + 'sprout/valarray/exponential.hpp', + 'sprout/valarray/gslice_array.hpp', + 'sprout/valarray/hash.hpp', + 'sprout/valarray/hyperbolic.hpp', + 'sprout/valarray/indirect_array.hpp', + 'sprout/valarray/logical.hpp', + 'sprout/valarray/make_valarray.hpp', + 'sprout/valarray/mask_array.hpp', + 'sprout/valarray/power.hpp', + 'sprout/valarray/slice_array.hpp', + 'sprout/valarray/trigonometric.hpp', + 'sprout/valarray/tuple.hpp', + 'sprout/valarray/type_traits.hpp', + 'sprout/valarray/valarray.hpp', + 'sprout/valarray/valarray_fwd.hpp', + 'sprout/variant.hpp', + 'sprout/variant/apply_visitor.hpp', + 'sprout/variant/as_variant_visitor.hpp', + 'sprout/variant/as_visitor.hpp', + 'sprout/variant/get.hpp', + 'sprout/variant/hash.hpp', + 'sprout/variant/io.hpp', + 'sprout/variant/static_variant_visitor.hpp', + 'sprout/variant/static_visitor.hpp', + 'sprout/variant/tuple.hpp', + 'sprout/variant/type_traits.hpp', + 'sprout/variant/variant.hpp', + 'sprout/variant/variant_fwd.hpp', + 'sprout/variant/visitor_result.hpp', + 'sprout/version.hpp', + 'sprout/weed.hpp', + 'sprout/weed/attr_cnv.hpp', + 'sprout/weed/attr_cnv/bitwise_or.hpp', + 'sprout/weed/attr_cnv/mem_ptr.hpp', + 'sprout/weed/attr_cnv/modulus.hpp', + 'sprout/weed/attr_cnv/negate.hpp', + 'sprout/weed/attr_cnv/results.hpp', + 'sprout/weed/attr_cnv/results/bitwise_or.hpp', + 'sprout/weed/attr_cnv/results/mem_ptr.hpp', + 'sprout/weed/attr_cnv/results/modulus.hpp', + 'sprout/weed/attr_cnv/results/negate.hpp', + 'sprout/weed/attr_cnv/results/shift_left.hpp', + 'sprout/weed/attr_cnv/results/times.hpp', + 'sprout/weed/attr_cnv/shift_left.hpp', + 'sprout/weed/attr_cnv/times.hpp', + 'sprout/weed/context.hpp', + 'sprout/weed/context/parse_context.hpp', + 'sprout/weed/context/parse_context/operator.hpp', + 'sprout/weed/context/parse_context/operator/address_of.hpp', + 'sprout/weed/context/parse_context/operator/bitwise_or.hpp', + 'sprout/weed/context/parse_context/operator/dereference.hpp', + 'sprout/weed/context/parse_context/operator/logical_not.hpp', + 'sprout/weed/context/parse_context/operator/mem_ptr.hpp', + 'sprout/weed/context/parse_context/operator/minus.hpp', + 'sprout/weed/context/parse_context/operator/modulus.hpp', + 'sprout/weed/context/parse_context/operator/negate.hpp', + 'sprout/weed/context/parse_context/operator/shift_left.hpp', + 'sprout/weed/context/parse_context/operator/unary_plus.hpp', + 'sprout/weed/context/parse_context/terminal.hpp', + 'sprout/weed/context/parse_context/terminal/char_type.hpp', + 'sprout/weed/context/parse_context/terminal/parser.hpp', + 'sprout/weed/context/parse_context/terminal/string.hpp', + 'sprout/weed/context/parse_context_fwd.hpp', + 'sprout/weed/detail/bdigits.hpp', + 'sprout/weed/detail/c_str_as_string.hpp', + 'sprout/weed/detail/digits.hpp', + 'sprout/weed/detail/find_character_set.hpp', + 'sprout/weed/detail/is_both_tuple.hpp', + 'sprout/weed/detail/is_both_unused.hpp', + 'sprout/weed/detail/is_container_and_elem.hpp', + 'sprout/weed/detail/is_different_elem.hpp', + 'sprout/weed/detail/is_elem_and_container.hpp', + 'sprout/weed/detail/is_elem_and_tuple.hpp', + 'sprout/weed/detail/is_elem_and_unused.hpp', + 'sprout/weed/detail/is_same_container.hpp', + 'sprout/weed/detail/is_same_elem.hpp', + 'sprout/weed/detail/is_tuple_and_elem.hpp', + 'sprout/weed/detail/is_unused_and_elem.hpp', + 'sprout/weed/detail/ndigits.hpp', + 'sprout/weed/detail/odigits.hpp', + 'sprout/weed/detail/xdigits.hpp', + 'sprout/weed/eval_result.hpp', + 'sprout/weed/expr.hpp', + 'sprout/weed/expr/eval.hpp', + 'sprout/weed/expr/expr.hpp', + 'sprout/weed/expr/expr_fwd.hpp', + 'sprout/weed/expr/make_expr.hpp', + 'sprout/weed/expr/make_terminal.hpp', + 'sprout/weed/expr/make_terminal_or_expr.hpp', + 'sprout/weed/expr/tag.hpp', + 'sprout/weed/limited.hpp', + 'sprout/weed/operator.hpp', + 'sprout/weed/operator/address_of.hpp', + 'sprout/weed/operator/bitwise_or.hpp', + 'sprout/weed/operator/dereference.hpp', + 'sprout/weed/operator/logical_not.hpp', + 'sprout/weed/operator/mem_ptr.hpp', + 'sprout/weed/operator/minus.hpp', + 'sprout/weed/operator/modulus.hpp', + 'sprout/weed/operator/negate.hpp', + 'sprout/weed/operator/shift_left.hpp', + 'sprout/weed/operator/unary_plus.hpp', + 'sprout/weed/parse.hpp', + 'sprout/weed/parser.hpp', + 'sprout/weed/parser/auxiliary.hpp', + 'sprout/weed/parser/auxiliary/eoi.hpp', + 'sprout/weed/parser/auxiliary/eol.hpp', + 'sprout/weed/parser/auxiliary/eps.hpp', + 'sprout/weed/parser/char.hpp', + 'sprout/weed/parser/char/char.hpp', + 'sprout/weed/parser/char/char_class.hpp', + 'sprout/weed/parser/directive.hpp', + 'sprout/weed/parser/directive/as_array.hpp', + 'sprout/weed/parser/directive/as_tuple.hpp', + 'sprout/weed/parser/directive/omit.hpp', + 'sprout/weed/parser/directive/repeat.hpp', + 'sprout/weed/parser/directive/replace.hpp', + 'sprout/weed/parser/lim.hpp', + 'sprout/weed/parser/lit.hpp', + 'sprout/weed/parser/numeric.hpp', + 'sprout/weed/parser/numeric/bin.hpp', + 'sprout/weed/parser/numeric/hex.hpp', + 'sprout/weed/parser/numeric/int.hpp', + 'sprout/weed/parser/numeric/int_p.hpp', + 'sprout/weed/parser/numeric/oct.hpp', + 'sprout/weed/parser/numeric/uint.hpp', + 'sprout/weed/parser/numeric/uint_p.hpp', + 'sprout/weed/parser/parser_base.hpp', + 'sprout/weed/parser/string.hpp', + 'sprout/weed/parser/string/string.hpp', + 'sprout/weed/parser_result.hpp', + 'sprout/weed/traits.hpp', + 'sprout/weed/traits/expr.hpp', + 'sprout/weed/traits/expr/expr_of.hpp', + 'sprout/weed/traits/expr/is_expr.hpp', + 'sprout/weed/traits/expr/tag_of.hpp', + 'sprout/weed/traits/expr/terminal_of.hpp', + 'sprout/weed/traits/expr/terminal_or_expr_of.hpp', + 'sprout/weed/traits/parser.hpp', + 'sprout/weed/traits/parser/attribute_of.hpp', + 'sprout/weed/traits/parser/is_parser.hpp', + 'sprout/weed/traits/parser/limit_of.hpp', + 'sprout/weed/traits/type.hpp', + 'sprout/weed/traits/type/is_c_str.hpp', + 'sprout/weed/traits/type/is_char_type.hpp', + 'sprout/weed/traits/type/is_container.hpp', + 'sprout/weed/traits/type/is_string.hpp', + 'sprout/weed/traits/type/is_tuple.hpp', + 'sprout/weed/traits/type/is_unused.hpp', + 'sprout/weed/unused.hpp', + 'sprout/workaround.hpp', + 'sprout/workaround/base_class_construct.hpp', + 'sprout/workaround/detail/uniform_int_distribution.hpp', + 'sprout/workaround/enable_if_with_array.hpp', + 'sprout/workaround/recursive_function_template.hpp', + 'sprout/workaround/std/cstddef.hpp', + preserve_path: true, #meson v0.63.0 + ) +endif diff --git a/subprojects/sprout.wrap b/subprojects/sprout.wrap new file mode 100644 index 0000000..8c340f9 --- /dev/null +++ b/subprojects/sprout.wrap @@ -0,0 +1,7 @@ +[wrap-git] +url = https://github.com/bolero-MURAKAMI/Sprout.git +revision = head +patch_directory = sprout + +[provide] +dependency_names = sprout-20190615 diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 0000000..082b746 --- /dev/null +++ b/test/meson.build @@ -0,0 +1 @@ +subdir('unit') diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 4e5c5f2..1bf2eab 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -14,7 +14,7 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) target_include_directories(${PROJECT_NAME} - PRIVATE ${DUCKHANDY_SOURCE_DIR}/lib/Catch2/single_include + PRIVATE ${DUCKHANDY_SOURCE_DIR}/subprojects/Catch2/Catch2/single_include ) target_link_libraries(${PROJECT_NAME} diff --git a/test/unit/meson.build b/test/unit/meson.build new file mode 100644 index 0000000..7b60b7a --- /dev/null +++ b/test/unit/meson.build @@ -0,0 +1,19 @@ +catch2_dep = dependency('Catch2', fallback: ['Catch2', 'catch2_dep']) + +unit_test_prog = executable(meson.project_name(), + 'int_conv_test.cpp', + 'main.cpp', + 'endianness_test.cpp', + 'reversed_sized_array_test.cpp', + 'bitfield_pack_test.cpp', + 'resource_pool_test.cpp', + 'version_test.cpp', + 'tiger_test.cpp', + install: false, + dependencies: [sprout_dep, catch2_dep], + include_directories: [public_incl], +) + +test('unit_' + meson.project_name(), + unit_test_prog, +) From f04eb9f5d3f6b84ca2eb1f9044af99d517e33877 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Tue, 7 Jun 2022 16:51:37 +0200 Subject: [PATCH 50/60] Forgot this --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index ec90d25..0b91e72 100644 --- a/meson.build +++ b/meson.build @@ -14,6 +14,7 @@ duckhandy_dep = declare_dependency( ], dependencies: [sprout_dep], ) +meson.override_dependency(meson.project_name(), duckhandy_dep) if get_option('build_testing') subdir('test') From df2f614642ede31a80c9f31dcca5155431cd676d Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 15 Feb 2024 22:07:05 +0100 Subject: [PATCH 51/60] Build fix on newer Meson versions --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 0b91e72..d4467be 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('duckhandy', +project('duckhandy', get_option('build_testing') ? 'cpp' : '', version: '0.1.0', meson_version: '>=0.56.0', default_options: ['buildtype=release', 'cpp_std=gnu++20', 'b_ndebug=if-release'] From 100b1d557ef833bb17d3b44ad284cffb2a4e28ef Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 15 Feb 2024 22:35:58 +0100 Subject: [PATCH 52/60] Remove Catch2 submodule, use meson wrap Catch2 seems to be Meson-ready now so removing custom meson file too --- .gitmodules | 3 --- subprojects/Catch2.wrap | 6 ++++++ subprojects/Catch2/Catch2 | 1 - subprojects/Catch2/meson.build | 11 ----------- 4 files changed, 6 insertions(+), 15 deletions(-) create mode 100644 subprojects/Catch2.wrap delete mode 160000 subprojects/Catch2/Catch2 delete mode 100644 subprojects/Catch2/meson.build diff --git a/.gitmodules b/.gitmodules index a4caa47..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "lib/Catch2"] - path = subprojects/Catch2/Catch2 - url = https://github.com/catchorg/Catch2.git diff --git a/subprojects/Catch2.wrap b/subprojects/Catch2.wrap new file mode 100644 index 0000000..0e9ad77 --- /dev/null +++ b/subprojects/Catch2.wrap @@ -0,0 +1,6 @@ +[wrap-git] +revision = 05e10dfccc28c7f973727c54f850237d07d5e10f +url = https://github.com/catchorg/Catch2.git + +[provide] +catch2_dep = Catch2-3.5.2 diff --git a/subprojects/Catch2/Catch2 b/subprojects/Catch2/Catch2 deleted file mode 160000 index 531a149..0000000 --- a/subprojects/Catch2/Catch2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 531a149ae70dd4143ba1ac28e33d40ab612d3897 diff --git a/subprojects/Catch2/meson.build b/subprojects/Catch2/meson.build deleted file mode 100644 index 0eb0ce2..0000000 --- a/subprojects/Catch2/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -project('Catch2', - version: '2.13.6', - meson_version: '>=0.54.0', -) - -public_incl = include_directories('Catch2/single_include') -catch2_dep = declare_dependency( - include_directories: public_incl -) - -meson.override_dependency(meson.project_name(), catch2_dep) From 180c3389011f8ed8777e06eccc4226346c543de4 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 15 Feb 2024 23:14:45 +0100 Subject: [PATCH 53/60] Just leave 'cpp' in there It seems to be required now, but also '' is not a valid language and the whole get_option() thing is not working when duckhandy is a submodule. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index d4467be..51e481a 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('duckhandy', get_option('build_testing') ? 'cpp' : '', +project('duckhandy', 'cpp', version: '0.1.0', meson_version: '>=0.56.0', default_options: ['buildtype=release', 'cpp_std=gnu++20', 'b_ndebug=if-release'] From fc5f917970d90bb130289eb99394c5a9ffb40ea4 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Wed, 27 Mar 2024 15:56:33 +0100 Subject: [PATCH 54/60] Update copyright year --- .gitignore | 1 + include/duckhandy/MaxSizedArray.hpp | 2 +- include/duckhandy/MaxSizedArray.inl | 2 +- include/duckhandy/bitfield_pack.hpp | 2 +- include/duckhandy/cmake_on_off.h | 2 +- include/duckhandy/compatibility.h | 2 +- include/duckhandy/ducktypes.hpp | 2 +- include/duckhandy/endianness.hpp | 2 +- include/duckhandy/implem/AutomemBase.hpp | 2 +- include/duckhandy/implem/AutomemBase.inl | 2 +- include/duckhandy/implem/IteratorOnPtr.hpp | 2 +- include/duckhandy/implem/int_conv.hpp | 2 +- include/duckhandy/implem/reversed_sized_array_bt.hpp | 2 +- include/duckhandy/int_conv.hpp | 2 +- include/duckhandy/int_types.hpp | 2 +- include/duckhandy/lengthof.h | 2 +- include/duckhandy/resource_pool.hpp | 2 +- include/duckhandy/string_bt.hpp | 2 +- include/duckhandy/stringize.h | 2 +- include/duckhandy/tiger_bt.hpp | 2 +- include/duckhandy/tiger_bt.inl | 2 +- include/duckhandy/version_bt.hpp | 2 +- test/unit/bitfield_pack_test.cpp | 2 +- test/unit/endianness_test.cpp | 2 +- test/unit/int_conv_test.cpp | 2 +- test/unit/main.cpp | 2 +- test/unit/resource_pool_test.cpp | 2 +- test/unit/reversed_sized_array_test.cpp | 2 +- test/unit/tiger_test.cpp | 2 +- test/unit/version_test.cpp | 2 +- 30 files changed, 30 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 922973f..0aacaa6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ tags compile_commands.json .clangd +.cache diff --git a/include/duckhandy/MaxSizedArray.hpp b/include/duckhandy/MaxSizedArray.hpp index 5dda780..aa30ed9 100644 --- a/include/duckhandy/MaxSizedArray.hpp +++ b/include/duckhandy/MaxSizedArray.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/MaxSizedArray.inl b/include/duckhandy/MaxSizedArray.inl index 2e05f48..d1a0efe 100644 --- a/include/duckhandy/MaxSizedArray.inl +++ b/include/duckhandy/MaxSizedArray.inl @@ -1,4 +1,4 @@ -/* Copyright 2016-2020 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/bitfield_pack.hpp b/include/duckhandy/bitfield_pack.hpp index bccc161..1311571 100644 --- a/include/duckhandy/bitfield_pack.hpp +++ b/include/duckhandy/bitfield_pack.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/cmake_on_off.h b/include/duckhandy/cmake_on_off.h index 3daf77c..09ecfdf 100644 --- a/include/duckhandy/cmake_on_off.h +++ b/include/duckhandy/cmake_on_off.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/compatibility.h b/include/duckhandy/compatibility.h index 5797cbf..4dcb793 100644 --- a/include/duckhandy/compatibility.h +++ b/include/duckhandy/compatibility.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/ducktypes.hpp b/include/duckhandy/ducktypes.hpp index 58f9a06..98c27fb 100644 --- a/include/duckhandy/ducktypes.hpp +++ b/include/duckhandy/ducktypes.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/endianness.hpp b/include/duckhandy/endianness.hpp index af3dac4..e44bd5a 100644 --- a/include/duckhandy/endianness.hpp +++ b/include/duckhandy/endianness.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/AutomemBase.hpp b/include/duckhandy/implem/AutomemBase.hpp index ed45298..f9e93e9 100644 --- a/include/duckhandy/implem/AutomemBase.hpp +++ b/include/duckhandy/implem/AutomemBase.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/AutomemBase.inl b/include/duckhandy/implem/AutomemBase.inl index 89c7148..b3c2712 100644 --- a/include/duckhandy/implem/AutomemBase.inl +++ b/include/duckhandy/implem/AutomemBase.inl @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/IteratorOnPtr.hpp b/include/duckhandy/implem/IteratorOnPtr.hpp index 6f76ad7..8926760 100644 --- a/include/duckhandy/implem/IteratorOnPtr.hpp +++ b/include/duckhandy/implem/IteratorOnPtr.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/int_conv.hpp b/include/duckhandy/implem/int_conv.hpp index ca59424..d490865 100644 --- a/include/duckhandy/implem/int_conv.hpp +++ b/include/duckhandy/implem/int_conv.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index 9085b00..41b4ce8 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/int_conv.hpp b/include/duckhandy/int_conv.hpp index 34bd733..1ab9e20 100644 --- a/include/duckhandy/int_conv.hpp +++ b/include/duckhandy/int_conv.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/int_types.hpp b/include/duckhandy/int_types.hpp index 47bdc16..0970267 100644 --- a/include/duckhandy/int_types.hpp +++ b/include/duckhandy/int_types.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/lengthof.h b/include/duckhandy/lengthof.h index 650ab05..eba090e 100644 --- a/include/duckhandy/lengthof.h +++ b/include/duckhandy/lengthof.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/resource_pool.hpp b/include/duckhandy/resource_pool.hpp index e477e21..2ad48e0 100644 --- a/include/duckhandy/resource_pool.hpp +++ b/include/duckhandy/resource_pool.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/string_bt.hpp b/include/duckhandy/string_bt.hpp index 9d6cdb6..d0105c4 100644 --- a/include/duckhandy/string_bt.hpp +++ b/include/duckhandy/string_bt.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/stringize.h b/include/duckhandy/stringize.h index a805ad0..043aebb 100644 --- a/include/duckhandy/stringize.h +++ b/include/duckhandy/stringize.h @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/tiger_bt.hpp b/include/duckhandy/tiger_bt.hpp index 7281f7e..dd45002 100644 --- a/include/duckhandy/tiger_bt.hpp +++ b/include/duckhandy/tiger_bt.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021, Michele Santullo +/* Copyright 2016-2024, Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/tiger_bt.inl b/include/duckhandy/tiger_bt.inl index 8ec5a6c..fb6011b 100644 --- a/include/duckhandy/tiger_bt.inl +++ b/include/duckhandy/tiger_bt.inl @@ -1,4 +1,4 @@ -/* Copyright 2016-2021, Michele Santullo +/* Copyright 2016-2024, Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/version_bt.hpp b/include/duckhandy/version_bt.hpp index d29276b..0b90788 100644 --- a/include/duckhandy/version_bt.hpp +++ b/include/duckhandy/version_bt.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/bitfield_pack_test.cpp b/test/unit/bitfield_pack_test.cpp index 04cc14e..81e52d3 100644 --- a/test/unit/bitfield_pack_test.cpp +++ b/test/unit/bitfield_pack_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/endianness_test.cpp b/test/unit/endianness_test.cpp index 92902a9..7afdd98 100644 --- a/test/unit/endianness_test.cpp +++ b/test/unit/endianness_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index 9b3de00..8adaa82 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/main.cpp b/test/unit/main.cpp index f38d2a5..7602a0e 100644 --- a/test/unit/main.cpp +++ b/test/unit/main.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/resource_pool_test.cpp b/test/unit/resource_pool_test.cpp index 7821179..84a3ad7 100644 --- a/test/unit/resource_pool_test.cpp +++ b/test/unit/resource_pool_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/reversed_sized_array_test.cpp b/test/unit/reversed_sized_array_test.cpp index 5ffc05f..de30986 100644 --- a/test/unit/reversed_sized_array_test.cpp +++ b/test/unit/reversed_sized_array_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/tiger_test.cpp b/test/unit/tiger_test.cpp index bdcda38..e2d4cdd 100644 --- a/test/unit/tiger_test.cpp +++ b/test/unit/tiger_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/test/unit/version_test.cpp b/test/unit/version_test.cpp index cd6c86b..b8e903a 100644 --- a/test/unit/version_test.cpp +++ b/test/unit/version_test.cpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2021 Michele Santullo +/* Copyright 2016-2024 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify From cd85666005875a5755c471e9b20715dfc0c57622 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 19 Apr 2024 23:18:26 +0200 Subject: [PATCH 55/60] Fix build of unit tests --- .gitignore | 2 ++ subprojects/Catch2.wrap | 2 +- test/unit/bitfield_pack_test.cpp | 2 +- test/unit/endianness_test.cpp | 2 +- test/unit/int_conv_test.cpp | 2 +- test/unit/main.cpp | 4 ++-- test/unit/meson.build | 2 +- test/unit/resource_pool_test.cpp | 2 +- test/unit/reversed_sized_array_test.cpp | 2 +- test/unit/tiger_test.cpp | 2 +- test/unit/version_test.cpp | 2 +- 11 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 0aacaa6..d750cc0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ tags compile_commands.json .clangd .cache +subprojects/Catch2/ +subprojects/sprout/ diff --git a/subprojects/Catch2.wrap b/subprojects/Catch2.wrap index 0e9ad77..e19cab1 100644 --- a/subprojects/Catch2.wrap +++ b/subprojects/Catch2.wrap @@ -3,4 +3,4 @@ revision = 05e10dfccc28c7f973727c54f850237d07d5e10f url = https://github.com/catchorg/Catch2.git [provide] -catch2_dep = Catch2-3.5.2 +Catch2 = catch2_with_main_dep diff --git a/test/unit/bitfield_pack_test.cpp b/test/unit/bitfield_pack_test.cpp index 81e52d3..8c7477a 100644 --- a/test/unit/bitfield_pack_test.cpp +++ b/test/unit/bitfield_pack_test.cpp @@ -15,7 +15,7 @@ * along with "duckhandy". If not, see . */ -#include "catch2/catch.hpp" +#include "catch2/catch_test_macros.hpp" #include "duckhandy/bitfield_pack.hpp" #include diff --git a/test/unit/endianness_test.cpp b/test/unit/endianness_test.cpp index 7afdd98..7bffe5b 100644 --- a/test/unit/endianness_test.cpp +++ b/test/unit/endianness_test.cpp @@ -15,7 +15,7 @@ * along with "duckhandy". If not, see . */ -#include "catch2/catch.hpp" +#include "catch2/catch_test_macros.hpp" #include "duckhandy/endianness.hpp" #include diff --git a/test/unit/int_conv_test.cpp b/test/unit/int_conv_test.cpp index 8adaa82..2067c42 100644 --- a/test/unit/int_conv_test.cpp +++ b/test/unit/int_conv_test.cpp @@ -15,7 +15,7 @@ * along with "duckhandy". If not, see . */ -#include "catch2/catch.hpp" +#include "catch2/catch_test_macros.hpp" #include "duckhandy/int_conv.hpp" #include "duckhandy/string_bt.hpp" #include "sprout/cstring/strlen.hpp" diff --git a/test/unit/main.cpp b/test/unit/main.cpp index 7602a0e..3befcdc 100644 --- a/test/unit/main.cpp +++ b/test/unit/main.cpp @@ -15,5 +15,5 @@ * along with "duckhandy". If not, see . */ -#define CATCH_CONFIG_MAIN -#include "catch2/catch.hpp" +//#define CATCH_CONFIG_MAIN +//#include "catch2/catch_test_macros.hpp" diff --git a/test/unit/meson.build b/test/unit/meson.build index 7b60b7a..bbf8914 100644 --- a/test/unit/meson.build +++ b/test/unit/meson.build @@ -1,4 +1,4 @@ -catch2_dep = dependency('Catch2', fallback: ['Catch2', 'catch2_dep']) +catch2_dep = dependency('Catch2', version: '>=3.5.2') unit_test_prog = executable(meson.project_name(), 'int_conv_test.cpp', diff --git a/test/unit/resource_pool_test.cpp b/test/unit/resource_pool_test.cpp index 84a3ad7..0d85a17 100644 --- a/test/unit/resource_pool_test.cpp +++ b/test/unit/resource_pool_test.cpp @@ -15,7 +15,7 @@ * along with "duckhandy". If not, see . */ -#include "catch2/catch.hpp" +#include "catch2/catch_test_macros.hpp" #include "duckhandy/resource_pool.hpp" #include diff --git a/test/unit/reversed_sized_array_test.cpp b/test/unit/reversed_sized_array_test.cpp index de30986..f3d6949 100644 --- a/test/unit/reversed_sized_array_test.cpp +++ b/test/unit/reversed_sized_array_test.cpp @@ -15,7 +15,7 @@ * along with "duckhandy". If not, see . */ -#include "catch2/catch.hpp" +#include "catch2/catch_test_macros.hpp" #include "duckhandy/implem/reversed_sized_array_bt.hpp" TEST_CASE ("Check conversion functions in ReversedSizedArray", "[ReversedSizedArray][containers]") { diff --git a/test/unit/tiger_test.cpp b/test/unit/tiger_test.cpp index e2d4cdd..9ad0dd9 100644 --- a/test/unit/tiger_test.cpp +++ b/test/unit/tiger_test.cpp @@ -15,7 +15,7 @@ * along with "duckhandy". If not, see . */ -#include "catch2/catch.hpp" +#include "catch2/catch_test_macros.hpp" #include "duckhandy/tiger_bt.hpp" TEST_CASE("Build-time Tiger hash tests", "[hash][bt][tiger]") { diff --git a/test/unit/version_test.cpp b/test/unit/version_test.cpp index b8e903a..e7c05ff 100644 --- a/test/unit/version_test.cpp +++ b/test/unit/version_test.cpp @@ -15,7 +15,7 @@ * along with "duckhandy". If not, see . */ -#include "catch2/catch.hpp" +#include "catch2/catch_test_macros.hpp" #include "duckhandy/version_bt.hpp" TEST_CASE ("Version class tests", "[version][bt]") { From d3092f93598ebc9d9fb1fd923562652036158820 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 25 Apr 2024 23:48:40 +0200 Subject: [PATCH 56/60] Update catch ref to 3.5.4 Fix noob mistake in previous commit --- subprojects/Catch2.wrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/Catch2.wrap b/subprojects/Catch2.wrap index e19cab1..3053b28 100644 --- a/subprojects/Catch2.wrap +++ b/subprojects/Catch2.wrap @@ -1,5 +1,5 @@ [wrap-git] -revision = 05e10dfccc28c7f973727c54f850237d07d5e10f +revision = b5373dadca40b7edc8570cf9470b9b1cb1934d40 url = https://github.com/catchorg/Catch2.git [provide] From 4d904ac689c988b4057ffb9fa92ab5238e98cdf2 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Fri, 26 Apr 2024 00:19:50 +0200 Subject: [PATCH 57/60] Fix deprecation warning Also put iterator into dhandy namespace. I don't remember why I left it out, and it's probably a sign I should have not done so. --- include/duckhandy/infix_iterator.hpp | 14 +++++-- test/unit/infix_iterator.cpp | 58 ++++++++++++++++++++++++++++ test/unit/meson.build | 1 + 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 test/unit/infix_iterator.cpp diff --git a/include/duckhandy/infix_iterator.hpp b/include/duckhandy/infix_iterator.hpp index ca65e34..a0d16db 100644 --- a/include/duckhandy/infix_iterator.hpp +++ b/include/duckhandy/infix_iterator.hpp @@ -5,12 +5,12 @@ #if !defined(INFIX_ITERATOR_H_) #define INFIX_ITERATOR_H_ #include -#include + +namespace dhandy { template > -class infix_ostream_iterator : - public std::iterator +class infix_ostream_iterator { std::basic_ostream *os; charT const* delimiter; @@ -19,6 +19,13 @@ public: typedef charT char_type; typedef traits traits_type; typedef std::basic_ostream ostream_type; + + using iterator_category = std::output_iterator_tag; + using value_type = void; + using difference_type = void; + using pointer = void; + using reference = void; + infix_ostream_iterator(ostream_type& s) : os(&s),delimiter(0), first_elem(true) {} @@ -45,4 +52,5 @@ public: return *this; } }; +} //namespace dhandy #endif diff --git a/test/unit/infix_iterator.cpp b/test/unit/infix_iterator.cpp new file mode 100644 index 0000000..9d32e81 --- /dev/null +++ b/test/unit/infix_iterator.cpp @@ -0,0 +1,58 @@ +/* Copyright 2016-2024 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#include "catch2/catch_test_macros.hpp" +#include "duckhandy/infix_iterator.hpp" +#include +#include +#include + +TEST_CASE("infix_iterator tests", "[iterator][infix_iterator]") { + using std::vector; + using std::string; + using std::copy; + using std::ostringstream; + using dhandy::infix_ostream_iterator; + + { + ostringstream oss; + vector empty{}; + copy(empty.begin(), empty.end(), infix_ostream_iterator(oss, "lalala")); + CHECK(oss.str() == ""); + } + + { + ostringstream oss; + vector data{"apple", "pear", "cherry", "mango"}; + copy(data.begin(), data.end(), infix_ostream_iterator(oss, "lalala")); + CHECK(oss.str() == "applelalalapearlalalacherrylalalamango"); + } + + { + ostringstream oss; + vector data{1, 2, 3, 4, 5, 6, 7}; + copy(data.begin(), data.end(), infix_ostream_iterator(oss, ", ")); + CHECK(oss.str() == "1, 2, 3, 4, 5, 6, 7"); + } + + { + ostringstream oss; + vector data{"just one value"}; + copy(data.begin(), data.end(), infix_ostream_iterator(oss, ", ")); + CHECK(oss.str() == "just one value"); + } +} diff --git a/test/unit/meson.build b/test/unit/meson.build index bbf8914..5ec1bd0 100644 --- a/test/unit/meson.build +++ b/test/unit/meson.build @@ -9,6 +9,7 @@ unit_test_prog = executable(meson.project_name(), 'resource_pool_test.cpp', 'version_test.cpp', 'tiger_test.cpp', + 'infix_iterator.cpp', install: false, dependencies: [sprout_dep, catch2_dep], include_directories: [public_incl], From cc129eb4e27afdff3b7668c7cd94d4d3e8c2998e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 23 Aug 2025 12:35:08 +0100 Subject: [PATCH 58/60] Update catch2 --- subprojects/Catch2.wrap | 3 ++- test/unit/meson.build | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/subprojects/Catch2.wrap b/subprojects/Catch2.wrap index 3053b28..973fd54 100644 --- a/subprojects/Catch2.wrap +++ b/subprojects/Catch2.wrap @@ -3,4 +3,5 @@ revision = b5373dadca40b7edc8570cf9470b9b1cb1934d40 url = https://github.com/catchorg/Catch2.git [provide] -Catch2 = catch2_with_main_dep +catch2-with-main = catch2_with_main_dep +Catch2 = catch2_dep diff --git a/test/unit/meson.build b/test/unit/meson.build index 5ec1bd0..7777af0 100644 --- a/test/unit/meson.build +++ b/test/unit/meson.build @@ -1,4 +1,4 @@ -catch2_dep = dependency('Catch2', version: '>=3.5.2') +catch2_dep = dependency('catch2-with-main', version: '>=3.5.2') unit_test_prog = executable(meson.project_name(), 'int_conv_test.cpp', From a2d6944249cdb05734b28fb6147337e385eb58e4 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 23 Aug 2025 12:36:29 +0100 Subject: [PATCH 59/60] New PackedPointer class --- include/duckhandy/bitfield_pack.hpp | 2 +- include/duckhandy/packed_pointer.hpp | 194 +++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 include/duckhandy/packed_pointer.hpp diff --git a/include/duckhandy/bitfield_pack.hpp b/include/duckhandy/bitfield_pack.hpp index 1311571..a140fbe 100644 --- a/include/duckhandy/bitfield_pack.hpp +++ b/include/duckhandy/bitfield_pack.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2024 Michele Santullo +/* Copyright 2016-2025 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/packed_pointer.hpp b/include/duckhandy/packed_pointer.hpp new file mode 100644 index 0000000..84aa8de --- /dev/null +++ b/include/duckhandy/packed_pointer.hpp @@ -0,0 +1,194 @@ +/* Copyright 2016-2025 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#ifndef id83CE9FAB90684250B98EA584C548E13F +#define id83CE9FAB90684250B98EA584C548E13F + +#include "bitfield_pack.hpp" +#include +#include +#include + +namespace dhandy { +namespace implem { + +//This monster expression is just the one-liner version of this +//implementation of log2: +//unsigned int v; // 32-bit value to find the log2 of +//register unsigned int r; // result of log2(v) will go here +//register unsigned int shift; +// +//r = (v > 0xFFFF) << 4; v >>= r; +//shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; +//shift = (v > 0xF ) << 2; v >>= shift; r |= shift; +//shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; +// r |= (v >> 1); +//see https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog for +//an explanation of that. +//This is a shorter version of it but it only works if the input is a power +//of 2: +//(((((NUM&0xAAAAAAAA)!=0)|((NUM&0xFFFF0000)!=0)<<4)|((NUM&0xFF00FF00)!=0)<< +//3)|((NUM&0xF0F0F0F0)!=0)<<2)|((NUM&0xCCCCCCCC)!=0)<<1 +//Source for that is also available at the page linked above. +template const constexpr std::size_t + pointer_unused_bit_count = + ((((((NUM > 0xFFFF) << 4) | (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << + 3)) | ((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << + 4)) > 0xFF) << 3)) > 0xF) << 2)) | (((((NUM >> ((NUM > 0xFFFF) << 4)) >> + (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) >> ((((NUM >> ((NUM > + 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) + << 2)) > 0x3) << 1)) | (((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ( + (NUM > 0xFFFF) << 4)) > 0xFF) << 3)) >> ((((NUM >> ((NUM > 0xFFFF) << 4) + ) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) << 2)) >> (( + (((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > + 0xFF) << 3)) >> ((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > + 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) << 2)) > 0x3) << 1)) >> 1)) +; + +template +BitfieldPack< + std::uintptr_t, + sizeof(std::uintptr_t) * CHAR_BIT - sizeof...(S), (S+1)/(S+1)... +> +guess_bitfield_type (std::index_sequence); + +template +using BaseBitfieldPackForPackedPointer = decltype( + implem::guess_bitfield_type( + std::make_index_sequence>() + ) +); +} //namespace implem + +template +class PackedPointer : private implem::BaseBitfieldPackForPackedPointer { + static_assert(sizeof(T*) == sizeof(std::uintptr_t), "Mismatching int/pointer size"); + typedef implem::BaseBitfieldPackForPackedPointer parent_type; +public: + static const constexpr std::size_t FlagsCount = parent_type::TotalEntries - 1; + + PackedPointer(); + PackedPointer (T* ptr); + ~PackedPointer() = default; + + operator T*() const; + operator bool() const; + template bool flag () const; + template void set_flag (bool v); + + PackedPointer& operator= (T* ptr); + T* operator->(); + const T* operator->() const; + T& operator*(); + const T& operator*() const; + bool operator== (const PackedPointer& other) const; + bool operator== (T* other) const; + bool operator!= (const PackedPointer& other) const; + bool operator!= (T* other) const; + +private: + //static const constexpr uintptr_t PtrMask = static_cast(-1) << FlagsCount; +}; + +template const constexpr std::size_t PackedPointer::FlagsCount; +//template const constexpr std::uintptr_t PackedPointer::PtrMask; + +template +PackedPointer::PackedPointer() : + PackedPointer(nullptr) +{ +} + +template +PackedPointer::PackedPointer (T* ptr) : + parent_type(0) +{ + (*this) = ptr; +} + +template +PackedPointer::operator T*() const { + return reinterpret_cast(this->get(0) << FlagsCount); +} + +template +PackedPointer::operator bool() const { + return static_cast(*this) != nullptr; +} + +template +template +bool PackedPointer::flag() const { + static_assert(Idx < FlagsCount, "Index out of range"); + return static_cast(this->get(Idx + 1)); +} + +template +template +void PackedPointer::set_flag (bool v) { + static_assert(Idx < FlagsCount, "Index out of range"); + this->set(Idx + 1, (v ? 1 : 0)); +} + +template +PackedPointer& PackedPointer::operator= (T* ptr) { + this->set(0, reinterpret_cast(ptr) >> FlagsCount); + return *this; +} + +template +T* PackedPointer::operator->() { + return static_cast(*this); +} + +template +const T* PackedPointer::operator->() const { + return static_cast(*this); +} + +template +T& PackedPointer::operator*() { + return *static_cast(*this); +} + +template +const T& PackedPointer::operator*() const { + return *static_cast(*this); +} + +template +bool PackedPointer::operator== (const PackedPointer& other) const { + return this == &other or static_cast(*this) == static_cast(other); +} + +template +bool PackedPointer::operator== (T* other) const { + return static_cast(*this) == other; +} + +template +bool PackedPointer::operator!= (const PackedPointer& other) const { + return not this->operator==(other); +} + +template +bool PackedPointer::operator!= (T* other) const { + return not this->operator==(other); +} +} //namepace dhandy + +#endif From 96c6ac1df3070beb833d3807f521af4b2bc15c4e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 23 Aug 2025 12:39:15 +0100 Subject: [PATCH 60/60] No idea what this is This stuff's been laying around for months and years, just committing and crossing fingers - pro coding here! --- .../implem/reversed_sized_array_bt.hpp | 27 +++++++++++- include/duckhandy/variadic_repeat_bt.hpp | 41 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 include/duckhandy/variadic_repeat_bt.hpp diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index 41b4ce8..257c80d 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -18,6 +18,7 @@ #ifndef idFC25566D624140559C54B39FFFE52F04 #define idFC25566D624140559C54B39FFFE52F04 +#include "../variadic_repeat_bt.hpp" #include #include #if !defined(INT_CONV_WITHOUT_HELPERS) @@ -37,13 +38,16 @@ namespace dhandy { using iterator = T*; constexpr ReversedSizedArray() = default; + constexpr ReversedSizedArray (const ReversedSizedArray&) = default; + constexpr ReversedSizedArray (ReversedSizedArray&&) = default; + template constexpr explicit ReversedSizedArray (Items&&... items); ~ReversedSizedArray() = default; constexpr std::size_t size() const { return S - (m_curr + 1); } constexpr bool empty() const { return m_curr + 1 == S; } constexpr const T operator[] (std::size_t idx) const { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; } constexpr T& operator[] (std::size_t idx) { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; } - constexpr void push_front (const T& itm) { if (size() == S) throw std::length_error("ReversedSizedArray is full"); m_data[m_curr--] = itm; } + constexpr void push_front (const T& itm) { /*if (size() == S) throw std::length_error("ReversedSizedArray is full");*/ m_data[m_curr--] = itm; } constexpr const T* data() const { return m_data + m_curr + 1; } constexpr const T* base_ptr() const { return m_data; } constexpr iterator begin() { return m_data + m_curr + 1; } @@ -67,6 +71,9 @@ namespace dhandy { #endif private: + template + constexpr explicit ReversedSizedArray (bt::variadic_repeat, Items&&... items); + T m_data[S]; std::size_t m_curr {S - 1}; }; @@ -78,6 +85,24 @@ namespace dhandy { } } //namespace implem + template + template + inline constexpr ReversedSizedArray::ReversedSizedArray (Items&&... items) : + ReversedSizedArray( + bt::make_variadic_repeat{}, + std::forward(items)... + ) + { } + + template + template + constexpr ReversedSizedArray::ReversedSizedArray (bt::variadic_repeat, Items&&... items) : + m_data{ItemsFill..., std::forward(items)...}, + m_curr(S - 1 - sizeof...(Items)) + { + static_assert(sizeof...(ItemsFill) + sizeof...(Items) == S, "Wrong number of input elements"); + } + #if !defined(INT_CONV_WITHOUT_HELPERS) template inline diff --git a/include/duckhandy/variadic_repeat_bt.hpp b/include/duckhandy/variadic_repeat_bt.hpp new file mode 100644 index 0000000..8c5262d --- /dev/null +++ b/include/duckhandy/variadic_repeat_bt.hpp @@ -0,0 +1,41 @@ +/* Copyright 2016-2024 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#include + +namespace dhandy::bt { +template +struct variadic_repeat { +}; + +namespace detail { + template + struct VariadicRepeatBuilder; + + template + struct VariadicRepeatBuilder<0, T, V0, V...> { + typedef variadic_repeat type; + }; + + template + struct VariadicRepeatBuilder : public VariadicRepeatBuilder { + }; +} //namespace detail + +template +using make_variadic_repeat = typename detail::VariadicRepeatBuilder::type; +} //namespace dhandy::bt