Skip to content

Commit

Permalink
Update pointer_set to use the new struct naive_index_iterator
Browse files Browse the repository at this point in the history
Signed-off-by: yamacir-kit <[email protected]>
  • Loading branch information
yamacir-kit committed Nov 18, 2023
1 parent 398b3a8 commit 75c5d56
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 36 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cd build
make package
sudo apt install build/meevax_0.5.84_amd64.deb
sudo apt install build/meevax_0.5.85_amd64.deb
```

or
Expand Down Expand Up @@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax

| Target Name | Description
|-------------|-------------
| `all` | Build shared-library `libmeevax.0.5.84.so` and executable `meevax`
| `all` | Build shared-library `libmeevax.0.5.85.so` and executable `meevax`
| `test` | Test executable `meevax`
| `package` | Generate debian package `meevax_0.5.84_amd64.deb`
| `package` | Generate debian package `meevax_0.5.85_amd64.deb`
| `install` | Copy files into `/usr/local` directly

## Usage
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5.84
0.5.85
17 changes: 10 additions & 7 deletions include/meevax/bitset/simple_bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,32 @@
#define INCLUDED_MEEVAX_BITSET_SIMPLE_BITSET_HPP

#include <array>
#include <bitset>

namespace meevax
{
inline namespace bitset
{
template <auto N>
struct simple_bitset
struct simple_bitset : public std::array<bool, N>
{
std::array<bool, N> data {};
constexpr simple_bitset()
: std::array<bool, N> {}
{}

auto test(std::size_t i) const noexcept -> bool
auto reset(std::size_t i) noexcept -> void
{
return data[i];
(*this)[i] = false;
}

auto set(std::size_t i) noexcept -> void
{
data[i] = true;
(*this)[i] = true;
}

auto reset(std::size_t i) noexcept -> void
auto test(std::size_t i) const noexcept -> bool
{
data[i] = false;
return (*this)[i];
}
};
} // namespace bitset
Expand Down
117 changes: 117 additions & 0 deletions include/meevax/iterator/naive_index_iterator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
Copyright 2018-2023 Tatsuya Yamasaki.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef INCLUDED_MEEVAX_ITERATOR_NAIVE_INDEX_ITERATOR_HPP
#define INCLUDED_MEEVAX_ITERATOR_NAIVE_INDEX_ITERATOR_HPP

#include <functional> // reference_wrapper
#include <iterator>
#include <limits>
#include <memory>
#include <type_traits>

namespace meevax
{
inline namespace iterator
{
template <typename Container>
struct naive_index_iterator
{
using iterator_category = std::bidirectional_iterator_tag;

using value_type = std::decay_t<decltype(std::declval<Container>()[std::declval<std::size_t>()])>;

using reference = decltype(std::declval<Container>()[std::declval<std::size_t>()]);

using pointer = std::add_pointer_t<value_type>;

using difference_type = std::ptrdiff_t;

std::reference_wrapper<Container const> container;

std::size_t index;

explicit naive_index_iterator(Container const& container)
: container { std::cref(container) }
, index { container.size() }
{}

explicit naive_index_iterator(Container const& container, std::size_t index)
: container { std::cref(container) }
, index { index }
{
if (container.size() < index)
{
index = container.size();
}
}

auto operator *() const -> decltype(auto)
{
assert(index < container.get().size());
return container.get()[index];
}

auto operator ++() -> decltype(auto)
{
/*
NOTE: Incrementing the end iterator is undefined behavior, so there is
no need to consider that case.
*/
assert(index < container.get().size());

++index;

assert(index <= container.get().size());

return *this;
}

auto operator --() -> decltype(auto)
{
/*
NOTE: Decrementing the begin iterator is undefined behavior, so there
is no need to consider that case.
*/
assert(index != 0);

--index;

assert(index < container.get().size());

return *this;
}

friend auto operator ==(naive_index_iterator const& a, naive_index_iterator const& b)
{
/*
NOTE: Comparing iterators obtained from different containers is
undefined behavior. Therefore, here, it may be assumed that
a.container and b.container refer to the same container, meaning that
they have the same address.
*/
return a.index == b.index;
}

friend auto operator !=(naive_index_iterator const& a, naive_index_iterator const& b)
{
return not (a == b);
}
};
} // namespace iterator
} // namespace meevax

#endif // INCLUDED_MEEVAX_ITERATOR_NAIVE_INDEX_ITERATOR_HPP
104 changes: 79 additions & 25 deletions include/meevax/memory/pointer_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,21 @@
#include <cstdint>
#include <iterator>
#include <limits>
#include <optional>
#include <type_traits>
#include <vector>

#include <meevax/bit/log2.hpp>
#include <meevax/bitset/simple_bitset.hpp>
#include <meevax/iterator/naive_index_iterator.hpp>

namespace meevax
{
inline namespace memory
{
template <typename Pointer,
template <std::size_t> typename Bitset = simple_bitset,
std::size_t N = 1024 * 1024>
std::size_t N = 4096 * 8> // getconf PAGE_SIZE
class pointer_set
{
static_assert(std::is_pointer_v<Pointer>);
Expand Down Expand Up @@ -79,6 +81,16 @@ inline namespace memory
{
Bitset<N>::set(p.index());
}

auto begin() const
{
return naive_index_iterator(*this, 0);
}

auto end() const
{
return naive_index_iterator(*this);
}
};

std::vector<chunk> chunks;
Expand All @@ -100,16 +112,16 @@ inline namespace memory

std::size_t i;

std::size_t j;
std::optional<naive_index_iterator<chunk>> inner;

explicit iterator(std::vector<chunk> const& chunks,
typename std::vector<chunk>::const_iterator iter,
std::size_t j) noexcept
: chunks { chunks }
, i { static_cast<std::size_t>(std::distance(chunks.begin(), iter)) }
, j { j }
, inner { i < chunks.size() ? std::make_optional(naive_index_iterator(chunks[i], j)) : std::nullopt }
{
if (not (i < chunks.size() and j < N and chunks[i].test(j)))
if (not dereferenceable() and incrementable())
{
operator ++();
}
Expand All @@ -118,32 +130,61 @@ inline namespace memory
explicit iterator(std::vector<chunk> const& chunks) noexcept
: chunks { chunks }
, i { chunks.size() }
, j { N }
{}
, inner { std::nullopt }
{
assert(not dereferenceable());
}

auto incrementable() const -> bool
{
return i < chunks.size() and inner;
}

auto decrementable() const -> bool
{
return i != 0 or inner != chunks[i].begin();
}

auto dereferenceable() const -> bool
{
return incrementable() and **inner;
}

auto operator *() const noexcept
{
return compact_pointer::to_pointer(chunks[i].offset + j);
assert(dereferenceable());
return compact_pointer::to_pointer(chunks[i].offset + inner->index);
}

auto operator ++() noexcept -> auto &
{
++j;
assert(incrementable());

/*
NOTE: Incrementing the end iterator is undefined behavior, so there
is no need to consider that case.
*/
if (++*inner == chunks[i].end())
{
inner = chunks[++i].begin();
}

for (; i < chunks.size(); ++i, j = 0)
assert(decrementable());

for (; i < chunks.size(); inner = chunks[++i].begin())
{
for (; j < N; ++j)
for (; inner != chunks[i].end(); ++*inner)
{
if (chunks[i].test(j))
if (**inner)
{
return *this;
}
}
}

i = chunks.size();
assert(i == chunks.size());

j = N;
inner = std::nullopt;

return *this; // end
}
Expand All @@ -157,29 +198,42 @@ inline namespace memory

auto operator --() noexcept -> auto &
{
i = std::min(chunks.size() - 1, i);
auto decrement_inner = [this]()
{
assert(decrementable());

j = std::min(N - 1, j - 1);
if (i == chunks.size() or inner == chunks[i].begin())
{
inner = std::prev(chunks[--i].end());
}
else
{
--*inner;
}

/*
NOTE: N4659 6.9.1.4
assert(incrementable());
};

Unsigned integers shall obey the laws of arithmetic modulo 2 n where
n is the number of bits in the value representation of that
particular size of integer.
*/
for (; i < chunks.size(); --i, j = N - 1)
decrement_inner();

for (; i < chunks.size(); inner = std::prev(chunks[--i].end()))
{
for (; j < N; --j)
while (true)
{
if (chunks[i].test(j))
if (**inner)
{
return *this;
}

decrement_inner();
}
}

#if defined(__GNUC__) or defined(__clang__)
__builtin_unreachable(); // Reaching here means decrementing the begin iterator. This is undefined behavior.
#else
return *this;
#endif
}

auto operator --(int) noexcept
Expand All @@ -191,7 +245,7 @@ inline namespace memory

auto operator ==(iterator const& rhs) const noexcept
{
return i == rhs.i and j == rhs.j;
return i == rhs.i and inner == rhs.inner;
}

auto operator !=(iterator const& rhs) const noexcept
Expand Down

0 comments on commit 75c5d56

Please sign in to comment.