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 SetBlock(std::size_t i, Block block);
|
||||
|
||||
void ShiftLeft(std::size_t pos);
|
||||
void ShiftRight(std::size_t pos);
|
||||
|
||||
void Swap(Bitset& bitset);
|
||||
|
||||
bool Test(std::size_t bit) const;
|
||||
|
|
@ -88,6 +91,12 @@ namespace Nz
|
|||
template<typename T> Bitset& operator=(T value);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Bitset.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Math/Algorithm.hpp>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
|
@ -512,12 +514,117 @@ namespace Nz
|
|||
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
|
||||
*
|
||||
* \param bitset Other bitset to swap
|
||||
*/
|
||||
|
||||
template<typename Block, class Allocator>
|
||||
void Bitset<Block, Allocator>::Swap(Bitset& bitset)
|
||||
{
|
||||
|
|
@ -763,6 +870,80 @@ namespace Nz
|
|||
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
|
||||
* \return A reference to this
|
||||
|
|
|
|||
Loading…
Reference in New Issue