From 6986d66f6ba30a188901ad11c43fc58a9fc6e302 Mon Sep 17 00:00:00 2001 From: Krish Munot Date: Sun, 9 Jul 2017 00:00:09 +0000 Subject: [PATCH] Revert "Trees and Graphs: C++14 solutions for tasks 4.11, 4.12 and Bit Manipulation: 5.1 to 5.4." --- .../C++14/4.11-RandomNode.cpp | 117 ---------------- .../C++14/4.11m-RandomTree.cpp | 127 ------------------ .../C++14/4.12-PathsWithSum.cpp | 50 ------- .../C++14/4.8-FirstCommonAncestor.cpp | 4 +- Ch 4. Trees and Graphs /C++14/tree.hpp | 5 +- .../C++14/treenodeiterator.hpp | 29 ++-- .../C++14/treetestutils.hpp | 39 +++--- .../C++14/5.1-Insertion.cpp | 29 ---- .../C++14/5.2-BinaryToString.cpp | 84 ------------ .../C++14/5.3-FlipBitToWin.cpp | 51 ------- .../C++14/5.4-NextNumber.cpp | 105 --------------- Ch 5. Bit Manipulation/C++14/bitutils.hpp | 38 ------ 12 files changed, 34 insertions(+), 644 deletions(-) delete mode 100644 Ch 4. Trees and Graphs /C++14/4.11-RandomNode.cpp delete mode 100644 Ch 4. Trees and Graphs /C++14/4.11m-RandomTree.cpp delete mode 100644 Ch 4. Trees and Graphs /C++14/4.12-PathsWithSum.cpp delete mode 100644 Ch 5. Bit Manipulation/C++14/5.1-Insertion.cpp delete mode 100644 Ch 5. Bit Manipulation/C++14/5.2-BinaryToString.cpp delete mode 100644 Ch 5. Bit Manipulation/C++14/5.3-FlipBitToWin.cpp delete mode 100644 Ch 5. Bit Manipulation/C++14/5.4-NextNumber.cpp delete mode 100644 Ch 5. Bit Manipulation/C++14/bitutils.hpp diff --git a/Ch 4. Trees and Graphs /C++14/4.11-RandomNode.cpp b/Ch 4. Trees and Graphs /C++14/4.11-RandomNode.cpp deleted file mode 100644 index 9ec4ac2..0000000 --- a/Ch 4. Trees and Graphs /C++14/4.11-RandomNode.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Random Node: You are implementing a binary search tree class from scratch, which, in addition -// to insert, find, and delete, has a method getRandomNode() which returns a random node -// from the tree. All nodes should be equally likely to be chosen. Design and implement an algorithm -// for getRandomNode, and explain how you would implement the rest of the methods. - -// Tree contains all nodes in a deque. It needs to handle insert() and delete() methods. -// getRundomNode: O(1) time -// To fill tree with deque additional: + O(N) time + O(N) memory. -// To clean tree with deque additional: + O(N) time - -#include -#include -#include -#include -#include - -template -class Tree -{ -public: - Tree() - { - // construct a trivial random generator engine from a time-based seed: - auto seed = std::chrono::system_clock::now().time_since_epoch().count(); - randomEngine = std::default_random_engine(seed); - } - - class RandomNode; - using NodePtr = std::shared_ptr; - - class RandomNode - { - public: - template - explicit RandomNode(U &&value) : v(std::forward(value)) - { - } - - const NodePtr &left() const - { - return childs[0]; - } - const NodePtr &right() const - { - return childs[1]; - } - const T &value() const - { - return v; - } - - private: - std::array childs; - T v; - size_t idx; // index in the Tree::nodes, used for quick deletion from Tree::nodes - friend class Tree; - }; - - template - const NodePtr insert(const NodePtr &parent, U &&value, bool insertRight) - { - NodePtr newNode; - if (!parent) - rootNode = newNode = std::make_shared(std::forward(value)); - else - parent->childs[insertRight ? 1 : 0] = newNode = std::make_shared(std::forward(value)); - newNode->idx = nodes.size(); - nodes.push_back(newNode); - return newNode; - } - - const NodePtr getRundomNode() const - { - if (nodes.size() == 0) - return nullptr; - else if (nodes.size() == 1) - return rootNode; - else - { - if (randomDistribution.max() != nodes.size() - 1) - randomDistribution = std::uniform_int_distribution(0, nodes.size() - 1); - return nodes.at(randomDistribution(randomEngine)); - } - } - - const NodePtr &root() const - { - return this->rootNode; - } - -private: - NodePtr rootNode; - std::deque nodes; - mutable std::default_random_engine randomEngine; - mutable std::uniform_int_distribution randomDistribution; -}; - -int main() -{ - Tree tree; - auto node = tree.insert(nullptr, 3, false); // 3 - auto left = tree.insert(node, 1, false); // / \ . - tree.insert(left, 0, false); // 1 5 - tree.insert(left, 2, true); // / \ / \ . - auto right = tree.insert(node, 5, true); // 0 2 4 6 - tree.insert(right, 4, false); - tree.insert(right, 6, true); - - std::string coma; - for (int i = 0; i < 100; ++i) - { - std::cout << coma << tree.getRundomNode()->value(); - if (coma.empty()) - coma = ", "; - } - std::cout << std::endl; -} diff --git a/Ch 4. Trees and Graphs /C++14/4.11m-RandomTree.cpp b/Ch 4. Trees and Graphs /C++14/4.11m-RandomTree.cpp deleted file mode 100644 index 355c904..0000000 --- a/Ch 4. Trees and Graphs /C++14/4.11m-RandomTree.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Random Node: You are implementing a binary search tree class from scratch, which, in addition -// to insert, find, and delete, has a method getRandomNode() which returns a random node -// from the tree. All nodes should be equally likely to be chosen. Design and implement an algorithm -// for getRandomNode, and explain how you would implement the rest of the methods. - -// Another solution with custom node implementation for balanced tree. -// getRundomNode: O(log(N)) time -// To fill tree from sorted array: O(N) time and O(N) memory. - -#include -#include -#include -#include "tree.hpp" -#include "treetestutils.hpp" - -template -class RandomNode; - -template -class RandomNode -{ -public: - using NodePtr = std::shared_ptr>; - - RandomNode(const T &v): size(1) - { - value = v; - } - - const NodePtr &getLeft() const - { - return childs[0]; - } - - const NodePtr &getRight() const - { - return childs[1]; - } - - const T &getValue() const - { - return value; - } - -private: - void add(const T &v) - { - if (!childs[v > value]) - childs[v > value] = std::make_shared>(v); - else - childs[v > value]->add(v); - ++size; - } - - const T &getRandom() const - { - return get(std::rand() % size + 1); - } - - const T &get(size_t n) const - { - if (n == size) - return value; - else if (childs[0] && n <= childs[0]->size) - return childs[0]->get(n); - else - return childs[1]->get(n - (childs[0] ? childs[0]->size : 0)); - } - - T value; - size_t size; - std::array childs; - - template - friend class RandomTree; -}; - -template -class RandomTree : public Tree -{ - using Base = Tree; - -public: - const T &getRandom() const - { - if (!Base::root) - throw typename Base::TreeIsEmptyException(); - return Base::root->getRandom(); - } - - void add(const T &value) - { - if (Base::root) - Base::root->add(value); - else - Base::root = std::make_shared>(value); - } -}; - - -int main() -{ - std::srand (unsigned(std::time(0))); - std::vector v(7) ; - std::iota(std::begin(v), std::end(v), 0); // Fill with 0, 1, ..., nodeCount - 1. - std::random_shuffle(std::begin(v), std::end(v), [](int i){return std::rand() % i;}); - - RandomTree tree; - tree.add(v.back()); - v.pop_back(); - for (auto i : v) - tree.add(i); - - TestUtils::printTree(tree); - std::cout << std::endl; - - // Check distribution of rundom tree nodes - v = std::vector(v.size() + 1, 0); - for (auto i = 0U; i < v.size() * 1000; ++i) - ++v[tree.getRandom()]; - - size_t cnt = std::accumulate(v.begin(), v.end(), 0); - std::cout << "Total: " << cnt << " times\n"; - std::cout << std::fixed << std::setprecision(2); - for (auto i = 0U; i < v.size(); ++i) - std::cout << i << ": " << 100.0 * v[i] / cnt << "%\n"; -} diff --git a/Ch 4. Trees and Graphs /C++14/4.12-PathsWithSum.cpp b/Ch 4. Trees and Graphs /C++14/4.12-PathsWithSum.cpp deleted file mode 100644 index ea3fc25..0000000 --- a/Ch 4. Trees and Graphs /C++14/4.12-PathsWithSum.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Paths with Sum: You are given a binary tree in which each node contains an integer value (which -// might be positive or negative). Design an algorithm to count the number of paths that sum to a -// given value. The path does not need to start or end at the root or a leaf, but it must go downwards -// (traveling only from parent nodes to child nodes). - -#include - -#include "tree.hpp" -#include "treetestutils.hpp" - -int sumsFrom(const NodePtr &node, int requiredSum, int pathSum, std::unordered_map &sums) -{ - if (!node) - return 0; - - pathSum += node->getValue(); - - // Count of paths ending here and having required sum - int overflow = pathSum - requiredSum; - int cnt = sums.count(overflow) ? sums.at(overflow) : 0; - - // Starting from root - if (pathSum == requiredSum) - ++cnt; - - sums[pathSum] += 1; - cnt += sumsFrom(node->getLeft(), requiredSum, pathSum, sums); - cnt += sumsFrom(node->getRight(), requiredSum, pathSum, sums); - - // Done with this node, do not use pathSum till this node anymore - if ((sums[pathSum] -= 1) == 0) - sums.erase(pathSum); // less memory - return cnt; -} - -int countPathsWithSum(const Tree &tree, int sum) -{ - std::unordered_map tmp; - return sumsFrom(tree.getRoot(), sum, 0, tmp); -} - -int main() -{ - auto tree = TestUtils::treeFromArray({1, -2, 3, -5, 7, -11, 13, -1, 2, -3, 5, -7, 11, -1, 2, -3, 1, -2, 3, -7}); - TestUtils::printTree(tree); - - // From sum of negative values till sum of positive values - for (int i = -42; i <= 48; ++i) - std::cout << "Sum " << i << " can be reached in " << countPathsWithSum(tree, i) << " paths\n"; -} diff --git a/Ch 4. Trees and Graphs /C++14/4.8-FirstCommonAncestor.cpp b/Ch 4. Trees and Graphs /C++14/4.8-FirstCommonAncestor.cpp index 6464181..e2d3bc9 100644 --- a/Ch 4. Trees and Graphs /C++14/4.8-FirstCommonAncestor.cpp +++ b/Ch 4. Trees and Graphs /C++14/4.8-FirstCommonAncestor.cpp @@ -14,8 +14,8 @@ enum FindResult { NotFound, // node not found in subtree - FoundLeft, // node found in left subtree - FoundRight, // node found in right subtree + FoundLeft, // node not found in left subtree + FoundRight, // node not found in right subtree FoundEqual // node is subtree root }; diff --git a/Ch 4. Trees and Graphs /C++14/tree.hpp b/Ch 4. Trees and Graphs /C++14/tree.hpp index 99470d2..bd9de08 100644 --- a/Ch 4. Trees and Graphs /C++14/tree.hpp +++ b/Ch 4. Trees and Graphs /C++14/tree.hpp @@ -2,12 +2,11 @@ #include "treenode.hpp" -template class N = Node> +template class Tree { public: - using NodePtr = typename N::NodePtr; + using NodePtr = typename Node::NodePtr; const NodePtr &getRoot() const { diff --git a/Ch 4. Trees and Graphs /C++14/treenodeiterator.hpp b/Ch 4. Trees and Graphs /C++14/treenodeiterator.hpp index 7d032f7..500fc75 100644 --- a/Ch 4. Trees and Graphs /C++14/treenodeiterator.hpp +++ b/Ch 4. Trees and Graphs /C++14/treenodeiterator.hpp @@ -1,10 +1,9 @@ #pragma once #include -#include +#include "treenode.hpp" -template class Node> +template class IteratorBase { using NodePtr = typename Node::NodePtr; @@ -38,8 +37,8 @@ class IteratorBase std::weak_ptr> currNode; }; -template class Node> -class IteratorBase +template +class IteratorBase { using NodePtr = std::shared_ptr>; @@ -82,10 +81,10 @@ class IteratorBase std::stack parents; }; -template class Node> -class Iterator : public IteratorBase, T, NodeWithParent, Node> +template +class Iterator : public IteratorBase, T, NodeWithParent> { - using Super = IteratorBase, T, NodeWithParent, Node>; + using Super = IteratorBase, T, NodeWithParent>; using NodePtr = typename Node::NodePtr; public: @@ -106,17 +105,17 @@ class Iterator : public IteratorBase, T, NodeW } }; -template class Node> +template class Tree; -template class Node> -auto begin(const Tree &tree) +template +auto begin(const Tree &tree) { - return Iterator(tree.getRoot()); + return Iterator(tree.getRoot()); } -template class Node> -auto end(const Tree) +template +auto end(const Tree) { - return Iterator(); + return Iterator(); } diff --git a/Ch 4. Trees and Graphs /C++14/treetestutils.hpp b/Ch 4. Trees and Graphs /C++14/treetestutils.hpp index d650881..b4aa003 100644 --- a/Ch 4. Trees and Graphs /C++14/treetestutils.hpp +++ b/Ch 4. Trees and Graphs /C++14/treetestutils.hpp @@ -8,8 +8,7 @@ #include #include -template class Node> +template class Tree; template @@ -17,10 +16,10 @@ class Node; namespace TestUtils { - template class Node> - void printTree(const Tree &tree) + template + void printTree(const Tree &tree) { - using NodePtr = typename Tree::NodePtr; + using NodePtr = typename Tree::NodePtr; T minValue = std::numeric_limits::max(), maxValue = std::numeric_limits::min(); @@ -47,7 +46,7 @@ namespace TestUtils if (minValue < 0) ++digits; - const std::string placeholder(digits, ' '); + const std::string placeholder(digits + 1, ' '); std::queue queue; std::queue childs; @@ -57,18 +56,14 @@ namespace TestUtils do { // space between nodes - std::string space((size - 1) * (placeholder.length() + 1) + 1, ' '); + std::string space((size - 1) * placeholder.length() + 1, ' '); // margin std::cout << std::string(space.length() / 2, ' ');; while (!queue.empty()) { if (!queue.front()) - { - std::cout << placeholder << space; - childs.emplace(); - childs.emplace(); - } + std::cout << placeholder; else { std::cout << std::setw(digits) << std::right << queue.front()->getValue() << space; @@ -84,11 +79,11 @@ namespace TestUtils } // The function treeFromArray from the task 4.2 helps us to fill test trees. - template class N = Node> + template auto treeFromArray(const T *array, size_t size) { - using NodePtr = typename Tree::NodePtr; + using Node = ::Node; + using NodePtr = typename Tree::NodePtr; std::function subtreeFromArray = [&subtreeFromArray](const T *array, const NodePtr &parent, int start, int end) -> NodePtr @@ -97,30 +92,28 @@ namespace TestUtils return nullptr; int i = (start + end) / 2; - auto node = std::make_shared>(array[i], parent); + auto node = std::make_shared(array[i], parent); node->setLeftChild(subtreeFromArray(array, node, start, i - 1)); node->setRightChild(subtreeFromArray(array, node, i + 1, end)); return node; }; - Tree tree; + Tree tree; tree.setRoot(subtreeFromArray(&array[0], nullptr, 0, size - 1)); return tree; } - template class N = Node> + template auto treeFromArray(std::initializer_list array) { - return treeFromArray(array.begin(), array.size()); + return treeFromArray(array.begin(), array.size()); } - template class N = Node> + template auto getSampleTree(size_t nodeCount) { std::vector v(nodeCount) ; std::iota(std::begin(v), std::end(v), 0); // Fill with 0, 1, ..., nodeCount - 1. - return treeFromArray(&v[0], v.size()); + return treeFromArray(&v[0], v.size()); } } diff --git a/Ch 5. Bit Manipulation/C++14/5.1-Insertion.cpp b/Ch 5. Bit Manipulation/C++14/5.1-Insertion.cpp deleted file mode 100644 index bc1e08b..0000000 --- a/Ch 5. Bit Manipulation/C++14/5.1-Insertion.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Insertion: You are given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method -// to insert M into N such that M starts at bit j and ends at bit i. You can assume that the bits j through -// i have enough space to fit all of M. That is, if M = 10011, you can assume that there are at least 5 -// bits between j and i. You would not, for example, have j = 3 and i = 2, because M could not fully -// fit between bit 3 and bit 2. -// EXAMPLE -// Input: N = 10000000000, M = 10011, i = 2, j = 6 -// Output: N = 10001001100 - -#include -#include - -#include "bitutils.hpp" - -int32_t insertion(int32_t N, int32_t M, int i, int j) -{ - int w = j - i; - if (w <= 0) - return N; - - int32_t maskN = (~0 << (j + 1)) | ((1 << i) - 1); - return (N & maskN) | (M << i); -} - -int main() -{ - auto result = insertion(0b10000000000, 0b10011, 2, 6); - std::cout << bits(result); -} diff --git a/Ch 5. Bit Manipulation/C++14/5.2-BinaryToString.cpp b/Ch 5. Bit Manipulation/C++14/5.2-BinaryToString.cpp deleted file mode 100644 index f46683e..0000000 --- a/Ch 5. Bit Manipulation/C++14/5.2-BinaryToString.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Binary to String: Given a real number between 0 and 1 (e.g., 0.72) that is passed in as a double, -// print the binary representation. If the number cannot be represented accurately in binary with at -// most 32 characters, print "ERROR:' - -#include -#include -#include -#include -#include -#include - -std::string binaryToStringMul(double binary) -{ - std::stringstream str; - if (binary < 0 || binary > 1) - return "ERROR"; - if (binary == 1) - return "1"; - if (binary == 0) - return "0"; - - str << "0."; - - while (binary != 0) - { - if (str.tellp() > 32) - return "ERROR"; - - binary *= 2; - if (binary >= 1) - { - str << '1'; - binary -= 1; - } - else - str << '0'; - } - return str.str(); -} - -std::string binaryToStringDiv(double binary) -{ - std::stringstream str; - if (binary < 0 || binary > 1) - return "ERROR"; - if (binary == 1) - return "1"; - if (binary == 0) - return "0"; - - double mantissaBit = 0.5; - str << "0."; - - while (binary != 0) - { - if (str.tellp() > 32) - return "ERROR"; - - if (binary >= mantissaBit) - { - str << '1'; - binary -= mantissaBit; - } - else - str << '0'; - mantissaBit /= 2; - } - return str.str(); -} - -int main() -{ - double value = 0; - double frac = 1.0 / 2 + 1.0 / 8; - - std::cout << std::setprecision(std::numeric_limits::digits10 + 1); - - for (int i = 0; i < 10; ++i) - { - std::cout << value << ": " << binaryToStringMul(value) << "(b), " << binaryToStringDiv(value) << "(b)\n"; - value += frac; - frac /= 16; - } -} diff --git a/Ch 5. Bit Manipulation/C++14/5.3-FlipBitToWin.cpp b/Ch 5. Bit Manipulation/C++14/5.3-FlipBitToWin.cpp deleted file mode 100644 index 96e744b..0000000 --- a/Ch 5. Bit Manipulation/C++14/5.3-FlipBitToWin.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Flip Bit to Win: You have an integer and you can flip exactly one bit from a O to a 1. Write code to -// find the length of the longest sequence of 1 s you could create. -// EXAMPLE -// Input: 1775 (or: 11011101111) -// Output: 8 - -#include -#include -#include -#include -#include - -#include "bitutils.hpp" - -template -int flipToWin(T bits) -{ - static_assert(std::is_unsigned::value, "T must be unsigned integral type"); - - int result = 1; - int lenLeft = 0; - int lenRight = 0; - while (bits != 0) - { - if (bits & 1) - ++lenLeft; - else - { - // The current bit is 0 means that we counted right sequence length. - // If the next bit will be 0, then right sequence length will reset to 0. - lenRight = lenLeft; - lenLeft = 0; - } - bits >>= 1; - result = std::max(lenRight + lenLeft + 1, result); - } - // We can not flip bit to 1 if there was no bit 0 - return std::min(result, std::numeric_limits::digits); -} - -int main() -{ - for (auto testValue : { - 0b11011101111U - , 0b110111001111U - , 0b1100111001111U - , 0U - , ~0U - }) - std::cout << bits(testValue) << ": " << flipToWin(testValue) << std::endl; -} diff --git a/Ch 5. Bit Manipulation/C++14/5.4-NextNumber.cpp b/Ch 5. Bit Manipulation/C++14/5.4-NextNumber.cpp deleted file mode 100644 index 0a1f779..0000000 --- a/Ch 5. Bit Manipulation/C++14/5.4-NextNumber.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// Next Number: Given a positive integer, print the next smallest and the previous largest number that -// have the same number of 1 bits in their binary representation. - -#include -#include -#include "bitutils.hpp" - -template -std::tuple nextBiggerSmaller(T v) -{ - static_assert(std::is_unsigned::value, "T must be unsigned integral type"); - - auto result = std::make_tuple(0U, 0U); - T rightZeros = 0; // tail zero count - T rightOnes = 0; // count of tightmost ones between zeros - T zeroPos = 0; // first/rightmost zero of 01 bits - T tmp = v; - - while (tmp != 0 && !(tmp & 1)) - { - ++rightZeros; - tmp >>= 1; - } - while (tmp != 0 && (tmp & 1)) - { - ++rightOnes; - tmp >>= 1; - } - zeroPos = rightZeros + rightOnes; - if (0 < zeroPos && zeroPos < std::numeric_limits::digits) - { - tmp = v | (1 << zeroPos); // rightmost non-trailing zero to 1 - // at this point we have one more bit 1 - tmp &= ~((1 << zeroPos) - 1); // reset all bits right from previously set - tmp |= (1 << (rightOnes - 1)) - 1; // set rightOnes - 1 rightmost bits to 1 - std::get<1>(result) = tmp; - } - - rightOnes = rightZeros = 0; - tmp = v; - - while (tmp != 0 && (tmp & 1)) - { - ++rightOnes; - tmp >>= 1; - } - while (tmp != 0 && !(tmp & 1)) - { - ++rightZeros; - tmp >>= 1; - } - T onePos = rightZeros + rightOnes; // first/rightmost one of 10 bits - if (0 < onePos && onePos < std::numeric_limits::digits) - { - tmp = v & ~(1 << onePos); // rightmost non-trailing 1 to zero - // at this point we have one bit 1 less - tmp |= (1 << onePos) - 1; // set all bits right from previously reset to 0 - tmp &= ~((1 << (rightZeros - 1)) - 1); // reset rightZeros - 1 rightmost bits to 0 - std::get<0>(result) = tmp; - } - - return result; -} - -int main() -{ - for (uint16_t v : { - 0b11011101111U - , 0U - , 0b1111111111111111U - , 0b0111111111111111U - , 0b1111111111111110U}) - { - auto minMax = nextBiggerSmaller(v); - auto nextMin = std::get<1>(minMax); - auto prevMax = std::get<0>(minMax); - std::cout << v << " (" << bits(v) << "b " << countBits(v) << " bits)\nNext min: "; - if (nextMin > 0) - std::cout << nextMin << " (" << bits(nextMin) << "b " << countBits(static_cast(nextMin)) << " bits)"; - else - std::cout << "Not existing"; - std::cout << "\nPrev max: "; - if (prevMax > 0) - std::cout << prevMax << " (" << bits(prevMax) << "b " << countBits(static_cast(prevMax)) << " bits)"; - else - std::cout << "Not existing"; - std::cout << std::endl << std::endl; - } - - uint8_t v = 1; // rightmost - do - { - std::cout << bits(v) << '\n'; - v = std::get<1>(nextBiggerSmaller(v)); - } - while (v != 0); - std::cout << std::endl; - v = 1 << (std::numeric_limits::digits - 1); - do - { - std::cout << bits(v) << '\n'; - v = std::get<0>(nextBiggerSmaller(v)); - } - while (v != 0); -} diff --git a/Ch 5. Bit Manipulation/C++14/bitutils.hpp b/Ch 5. Bit Manipulation/C++14/bitutils.hpp deleted file mode 100644 index bb98a52..0000000 --- a/Ch 5. Bit Manipulation/C++14/bitutils.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -template ::digits> -std::bitset bits(const T &value) -{ - return std::bitset(value); -} - -template -size_t countBits(T v) -{ - //return std::bitset::digits>(v).count(); - - static_assert(std::is_unsigned::value, "T must be unsigned integral type"); - static_assert(std::numeric_limits::digits <= 64, "Max 64 bits of T supported"); - - constexpr const T m5 = static_cast(0x5555555555555555U); - constexpr const T m3 = static_cast(0x3333333333333333U); - constexpr const T m0F = static_cast(0x0F0F0F0F0F0F0F0FU); - v = v - ((v >> 1) & m5); // put count of each 2 bits into those 2 bits - v = (v & m3) + ((v >> 2) & m3); // put count of each 4 bits into those 4 bits - v = (v + (v >> 4)) & m0F; // put count of each byte bits into those bytes -# if 0 - constexpr const T m01 = static_cast(0x0101010101010101U); - v = (v * m01); // B7B6..B0 --> (B7+B6+...+B0) + (B6+B5+...+B0) + ... + B0 - return v >> (std::numeric_limits::digits - 8); -# else - if (std::numeric_limits::digits > 8) - v = (v + (v >> 8)); - if (std::numeric_limits::digits > 16) - v = (v + (v >> 16)); - if (std::numeric_limits::digits > 32) - v = (v + (v >> 32)); - return v & 0xFF; -# endif -}