Skip to content

Commit

Permalink
Hyper-tested dynamic_bitset/small_bit_vector
Browse files Browse the repository at this point in the history
  • Loading branch information
ThePhD committed Oct 13, 2019
1 parent bc8112c commit 9f4976a
Show file tree
Hide file tree
Showing 25 changed files with 3,672 additions and 2,225 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,9 @@ Likewise, the code should also be usable in a `-fno-exceptions` situation. It li
## Optimization Work

- There is a need to make the `bit_equal` and `std::equal` algorithms perform just as fast as their `memcmp` counterparts. The answer why it does not optimize out as cleanly will likely lie in an analysis of both the output assembly and any intermediate representation available from the compiler (LLVM and GCC can help obtain this kind of information). See the benchmarks for more details.
- `std::equal` should use `std::mismatch` internally if the sizes match (duplicate metaprogramming from standard libraries).
- Optimizations for `bit_iterator<T>`s that have different underlying `It` types is very much pertinent to what is happening here. The optimizations are very much done plainly and only work on homogenous iterators; it would be great to work on `bit_iterator`s that do not view the same `value_type` in the slightest.

- `small_bit_vector` needs a ton of help in various places for both Strong Exception Guarantee and optimization fast-paths for the bulk insertion functions.


# Acknowledgements
Expand All @@ -478,4 +479,6 @@ A huge thanks to Dr. Vincent Reverdy for sponsoring and helping with this work.

Many thanks to the Blessed Guardian, Morwenn, for watching over my commits and cautioning me of my occasional derps.

Thank you to Corentin Jabot for changing the name "Extents" to "Bounds" to better represent the begin/end type for `bit_view`.
Thanks to Griwes for giving me even more ideas for packed bit representations.

Thank you to Corentin Jabot for changing the name "Extents" to "Bounds" to better represent the `begin`/`end` type for `bit_view`.
12 changes: 8 additions & 4 deletions include/itsy/detail/bit_detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,22 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
{
};

template<typename Alloc, typename... Args>
using __allocator_construct_invocable_test =
decltype(::std::declval<Alloc>().construct(::std::declval<Args>()...));

template<typename _Type>
union __uninit
union alignas(_Type) __uninit
{
constexpr __uninit() : _M_dummy()
{
}

template<typename... _Args>
constexpr __uninit(::std::in_place_t, _Args&&... __args)
: _M_value(::std::forward<_Args>(__args)...){

};
: _M_value(::std::forward<_Args>(__args)...)
{
}

char _M_dummy;
_Type _M_value;
Expand Down
50 changes: 25 additions & 25 deletions include/itsy/detail/bit_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,19 +285,19 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
constexpr size_type
position() const noexcept
{
return __mask_to_pos<size_type>(_M_mask);
return __mask_to_pos<size_type>(this->_M_mask);
}

constexpr mask_type
mask() const noexcept
{
return _M_mask;
return this->_M_mask;
}

constexpr bool
value() const noexcept
{
return (_M_word & _M_mask) != static_cast<mask_type>(0);
return (this->_M_word & this->_M_mask) != static_cast<mask_type>(0);
}

constexpr ::std::add_pointer_t<__cv_word_type>
Expand Down Expand Up @@ -756,12 +756,12 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
// observers
constexpr reference operator*() const noexcept
{
return reference(*_M_base_it, _M_pos);
return reference(*this->_M_base_it, this->_M_pos);
}

constexpr pointer operator->() const noexcept
{
return pointer(_M_base_it, _M_pos);
return pointer(this->_M_base_it, this->_M_pos);
}

constexpr reference operator[](difference_type n) const
Expand All @@ -773,13 +773,13 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
constexpr iterator_type
base() const noexcept
{
return _M_base_it;
return this->_M_base_it;
}

constexpr size_type
position() const noexcept
{
return _M_pos;
return this->_M_pos;
}

constexpr __mask_type
Expand All @@ -792,11 +792,11 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
constexpr __bit_iterator&
operator++()
{
++_M_pos;
if (_M_pos == __binary_digits_v<__word_type>)
++this->_M_pos;
if (this->_M_pos == __binary_digits_v<__word_type>)
{
_M_pos = 0;
++_M_base_it;
this->_M_pos = 0;
++this->_M_base_it;
}

return *this;
Expand All @@ -805,14 +805,14 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
constexpr __bit_iterator&
operator--()
{
if (_M_pos == 0)
if (this->_M_pos == 0)
{
_M_pos = __max_binary_index_v<__word_type>;
--_M_base_it;
this->_M_pos = __max_binary_index_v<__word_type>;
--this->_M_base_it;
}
else
{
--_M_pos;
--this->_M_pos;
}

return *this;
Expand Down Expand Up @@ -862,18 +862,18 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
return *this;
}
__size_type __bit_advancement = __n % __binary_digits_v<__word_type>;
_M_pos += __bit_advancement;
if (_M_pos > __binary_digits_v<__word_type>)
this->_M_pos += __bit_advancement;
if (this->_M_pos > __binary_digits_v<__word_type>)
{
// put it back in the proper range
_M_pos -= __binary_digits_v<__word_type>;
this->_M_pos -= __binary_digits_v<__word_type>;
// going forward by one extra since we
// overflow binary digit count
::std::advance(_M_base_it, (__n / __binary_digits_v<__word_type>)+1);
::std::advance(this->_M_base_it, (__n / __binary_digits_v<__word_type>)+1);
return *this;
}

::std::advance(_M_base_it, __n / __binary_digits_v<__word_type>);
::std::advance(this->_M_base_it, __n / __binary_digits_v<__word_type>);
return *this;
}

Expand All @@ -890,19 +890,19 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
}
__size_type __bit_advancement = __n % __binary_digits_v<__word_type>;
difference_type __it_advancement = __n / __binary_digits_v<__word_type>;
if (__bit_advancement > _M_pos)
if (__bit_advancement > this->_M_pos)
{
// put it back in the proper range
_M_pos = __binary_digits_v<__word_type> - __bit_advancement;
this->_M_pos = __binary_digits_v<__word_type> - __bit_advancement;
// going forward by one extra since we
// overflow binary digit count
++__it_advancement;
::std::advance(_M_base_it, -__it_advancement);
::std::advance(this->_M_base_it, -__it_advancement);
return *this;
}

_M_pos -= __bit_advancement;
::std::advance(_M_base_it,
this->_M_pos -= __bit_advancement;
::std::advance(this->_M_base_it,
-static_cast<difference_type>(__n / __binary_digits_v<__word_type>));
return *this;
}
Expand Down
37 changes: 24 additions & 13 deletions include/itsy/detail/ebco.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,53 +22,60 @@
namespace ITSY_BITSY_DETAIL_NAMESPACE
{
template<typename _Type, ::std::size_t = 0, typename = void>
struct __ebco
class __ebco
{
_Type value;
private:
_Type _M_value;

public:
__ebco() = default;
__ebco(const __ebco&) = default;
__ebco(__ebco&&) = default;
__ebco&
operator=(const __ebco&) = default;
__ebco&
operator=(__ebco&&) = default;
__ebco(const _Type& v) : value(v){};
__ebco(_Type&& v) : value(::std::move(v)){};
__ebco(const _Type& v) : _M_value(v){};
__ebco(_Type&& v) : _M_value(::std::move(v)){};
__ebco&
operator=(const _Type& v)
{
value = v;
this->_M_value = v;
return *this;
}
__ebco&
operator=(_Type&& v)
{
value = ::std::move(v);
this->_M_value = ::std::move(v);
return *this;
};
template<typename Arg, typename... Args,
typename = ::std::enable_if_t<
!::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<Arg>>, __ebco> &&
!::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<Arg>>, _Type>>>
__ebco(Arg&& arg, Args&&... args)
: _Type(::std::forward<Arg>(arg), ::std::forward<Args>(args)...){};
: _M_value(::std::forward<Arg>(arg), ::std::forward<Args>(args)...)
{
}

_Type&
_M_get_value()
{
return value;
return this->_M_value;
}

_Type const&
_M_get_value() const
{
return value;
return this->_M_value;
}
};

template<typename _Type, ::std::size_t _Tag>
struct __ebco<_Type, _Tag,
::std::enable_if_t<::std::is_class_v<_Type> && !::std::is_final_v<_Type>>> : _Type
class __ebco<_Type, _Tag,
::std::enable_if_t<::std::is_class_v<_Type> && !::std::is_final_v<_Type>>> : private _Type
{
public:
__ebco() = default;
__ebco(const __ebco&) = default;
__ebco(__ebco&&) = default;
Expand All @@ -79,7 +86,9 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
!::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<Arg>>, __ebco> &&
!::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<Arg>>, _Type>>>
__ebco(Arg&& arg, Args&&... args)
: _Type(::std::forward<Arg>(arg), ::std::forward<Args>(args)...){};
: _Type(::std::forward<Arg>(arg), ::std::forward<Args>(args)...)
{
}

__ebco&
operator=(const __ebco&) = default;
Expand All @@ -89,12 +98,14 @@ namespace ITSY_BITSY_DETAIL_NAMESPACE
operator=(const _Type& v)
{
static_cast<_Type&>(*this) = v;
return *this;
}
__ebco&
operator=(_Type&& v)
{
static_cast<_Type&>(*this) = ::std::move(v);
};
return *this;
}

_Type&
_M_get_value()
Expand Down
Loading

0 comments on commit 9f4976a

Please sign in to comment.