Core/Bitset: Add bit shifting functions
Former-commit-id: a5d9aa0da769a1f5b70e5db8eed5c370e1e9b076 [formerly c8338571cedad83c557ffa9210f8e11a928157f2] [formerly 47e36d22755f77c878f5277a99f61388f096a449 [formerly 12f27f9470c490160deb869f83736c000bb18d93]] Former-commit-id: bc971c681a184ac7d340fa1d5b053f2e4a8cd156 [formerly 2a84c48ec1ab8970fb768dc5d925e7712cb193ea] Former-commit-id: 728cccf49da4bb48416aa91e3687fa7fad8035ef
This commit is contained in:
parent
d99cfa5181
commit
2b28b217d1
|
|
@ -64,6 +64,9 @@ namespace Nz
|
||||||
void Set(std::size_t bit, bool val = true);
|
void Set(std::size_t bit, bool val = true);
|
||||||
void SetBlock(std::size_t i, Block block);
|
void SetBlock(std::size_t i, Block block);
|
||||||
|
|
||||||
|
void ShiftLeft(std::size_t pos);
|
||||||
|
void ShiftRight(std::size_t pos);
|
||||||
|
|
||||||
void Swap(Bitset& bitset);
|
void Swap(Bitset& bitset);
|
||||||
|
|
||||||
bool Test(std::size_t bit) const;
|
bool Test(std::size_t bit) const;
|
||||||
|
|
@ -88,6 +91,12 @@ namespace Nz
|
||||||
template<typename T> Bitset& operator=(T value);
|
template<typename T> Bitset& operator=(T value);
|
||||||
Bitset& operator=(Bitset&& bitset) noexcept = default;
|
Bitset& operator=(Bitset&& bitset) noexcept = default;
|
||||||
|
|
||||||
|
Bitset operator<<(std::size_t pos) const;
|
||||||
|
Bitset& operator<<=(std::size_t pos);
|
||||||
|
|
||||||
|
Bitset operator>>(std::size_t pos) const;
|
||||||
|
Bitset& operator>>=(std::size_t pos);
|
||||||
|
|
||||||
Bitset& operator&=(const Bitset& bitset);
|
Bitset& operator&=(const Bitset& bitset);
|
||||||
Bitset& operator|=(const Bitset& bitset);
|
Bitset& operator|=(const Bitset& bitset);
|
||||||
Bitset& operator^=(const Bitset& bitset);
|
Bitset& operator^=(const Bitset& bitset);
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
// This file is part of the "Nazara Engine - Core module"
|
// This file is part of the "Nazara Engine - Core module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Core/Bitset.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Math/Algorithm.hpp>
|
#include <Nazara/Math/Algorithm.hpp>
|
||||||
|
#include <cstdlib>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
@ -512,12 +514,117 @@ namespace Nz
|
||||||
ResetExtraBits();
|
ResetExtraBits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shift all the bits toward the left
|
||||||
|
*
|
||||||
|
* \param pos Bit shifting to be applied
|
||||||
|
*
|
||||||
|
* \remark This does not changes the size of the bitset.
|
||||||
|
*
|
||||||
|
* \see operator<<=
|
||||||
|
*/
|
||||||
|
template<typename Block, class Allocator>
|
||||||
|
void Bitset<Block, Allocator>::ShiftLeft(std::size_t pos)
|
||||||
|
{
|
||||||
|
if (pos == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pos >= m_bitCount)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto div = std::lldiv(pos, bitsPerBlock);
|
||||||
|
if (div.rem != 0)
|
||||||
|
{
|
||||||
|
std::size_t lastIndex = m_blocks.size() - 1;
|
||||||
|
std::size_t remaining = bitsPerBlock - div.rem;
|
||||||
|
|
||||||
|
for (std::size_t i = lastIndex - div.quot; i > 0; --i)
|
||||||
|
m_blocks[i + div.quot] = (m_blocks[i] << div.rem) | (m_blocks[i - 1] >> remaining);
|
||||||
|
|
||||||
|
m_blocks[div.quot] = m_blocks[0] << div.rem;
|
||||||
|
|
||||||
|
std::fill_n(m_blocks.begin(), div.quot, Block(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto it = m_blocks.rbegin(); it != m_blocks.rend(); ++it)
|
||||||
|
{
|
||||||
|
if (static_cast<std::size_t>(std::distance(m_blocks.rbegin(), it) + div.quot) < m_blocks.size())
|
||||||
|
{
|
||||||
|
auto shiftedIt = it;
|
||||||
|
std::advance(shiftedIt, div.quot);
|
||||||
|
|
||||||
|
*it = *shiftedIt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*it = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetExtraBits();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shift all the bits toward the right
|
||||||
|
*
|
||||||
|
* \param pos Bit shifting to be applied
|
||||||
|
*
|
||||||
|
* \remark This does not changes the size of the bitset.
|
||||||
|
*
|
||||||
|
* \see operator>>=
|
||||||
|
*/
|
||||||
|
template<typename Block, class Allocator>
|
||||||
|
void Bitset<Block, Allocator>::ShiftRight(std::size_t pos)
|
||||||
|
{
|
||||||
|
if (pos == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pos >= m_bitCount)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto div = std::lldiv(pos, bitsPerBlock);
|
||||||
|
if (div.rem != 0)
|
||||||
|
{
|
||||||
|
std::size_t lastIndex = m_blocks.size() - 1;
|
||||||
|
std::size_t remaining = bitsPerBlock - div.rem;
|
||||||
|
|
||||||
|
for (std::size_t i = div.quot; i < last; ++i)
|
||||||
|
m_blocks[i - div.quot] = (m_blocks[i] >> div.rem) | (m_blocks[i + 1] << remaining);
|
||||||
|
|
||||||
|
m_blocks[last - div.quot] = m_blocks[last] >> div.rem;
|
||||||
|
|
||||||
|
std::fill_n(m_blocks.begin() + (m_blocks.size() - div.quot), div.quot, Block(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto it = m_blocks.begin(); it != m_blocks.end(); ++it)
|
||||||
|
{
|
||||||
|
if (static_cast<std::size_t>(std::distance(m_blocks.begin(), it) + div.quot) < m_blocks.size())
|
||||||
|
{
|
||||||
|
auto shiftedIt = it;
|
||||||
|
std::advance(shiftedIt, div.quot);
|
||||||
|
|
||||||
|
*it = *shiftedIt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*it = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetExtraBits();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Swaps the two bitsets
|
* \brief Swaps the two bitsets
|
||||||
*
|
*
|
||||||
* \param bitset Other bitset to swap
|
* \param bitset Other bitset to swap
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename Block, class Allocator>
|
template<typename Block, class Allocator>
|
||||||
void Bitset<Block, Allocator>::Swap(Bitset& bitset)
|
void Bitset<Block, Allocator>::Swap(Bitset& bitset)
|
||||||
{
|
{
|
||||||
|
|
@ -763,6 +870,80 @@ namespace Nz
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shift all the bits toward the left
|
||||||
|
*
|
||||||
|
* \param pos Bit shifting to be applied
|
||||||
|
*
|
||||||
|
* \return A copies of the bitset with shifted bits
|
||||||
|
*
|
||||||
|
* \remark This does not changes the size of the bitset.
|
||||||
|
*
|
||||||
|
* \see ShiftLeft
|
||||||
|
*/
|
||||||
|
template<typename Block, class Allocator>
|
||||||
|
Bitset<Block, Allocator> Bitset<Block, Allocator>::operator<<(std::size_t pos) const
|
||||||
|
{
|
||||||
|
Bitset bitset(*this);
|
||||||
|
return bitset <<= pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shift all the bits toward the left
|
||||||
|
*
|
||||||
|
* \param pos Bit shifting to be applied
|
||||||
|
*
|
||||||
|
* \return A reference to this
|
||||||
|
*
|
||||||
|
* \remark This does not changes the size of the bitset.
|
||||||
|
*
|
||||||
|
* \see ShiftLeft
|
||||||
|
*/
|
||||||
|
template<typename Block, class Allocator>
|
||||||
|
Bitset<Block, Allocator>& Bitset<Block, Allocator>::operator<<=(std::size_t pos)
|
||||||
|
{
|
||||||
|
ShiftLeft(pos);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shift all the bits toward the right
|
||||||
|
*
|
||||||
|
* \param pos Bit shifting to be applied
|
||||||
|
*
|
||||||
|
* \return A copies of the bitset with shifted bits
|
||||||
|
*
|
||||||
|
* \remark This does not changes the size of the bitset.
|
||||||
|
*
|
||||||
|
* \see ShiftRight
|
||||||
|
*/
|
||||||
|
template<typename Block, class Allocator>
|
||||||
|
Bitset<Block, Allocator> Bitset<Block, Allocator>::operator>>(std::size_t pos) const
|
||||||
|
{
|
||||||
|
Bitset bitset(*this);
|
||||||
|
return bitset >>= pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shift all the bits toward the right
|
||||||
|
*
|
||||||
|
* \param pos Bit shifting to be applied
|
||||||
|
*
|
||||||
|
* \return A reference to this
|
||||||
|
*
|
||||||
|
* \remark This does not changes the size of the bitset.
|
||||||
|
*
|
||||||
|
* \see ShiftRight
|
||||||
|
*/
|
||||||
|
template<typename Block, class Allocator>
|
||||||
|
Bitset<Block, Allocator>& Bitset<Block, Allocator>::operator>>=(std::size_t pos)
|
||||||
|
{
|
||||||
|
ShiftRight(pos);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Performs an "AND" with another bitset
|
* \brief Performs an "AND" with another bitset
|
||||||
* \return A reference to this
|
* \return A reference to this
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue