Commit a7ad24fc authored by Baptiste Esteban's avatar Baptiste Esteban
Browse files

Change level index to int in directional hqueue

parent 77fc3128
Pipeline #27853 passed with stages
in 14 minutes and 40 seconds
......@@ -12,15 +12,12 @@ namespace mln::morpho::details
/// \brief Directional hierarchical queue
/// \tparam I The image the edges are calculated from
/// \tparam N The neighborhood used to compute the edges
/// \tparam F The distance function
template <typename I, typename N, typename F>
/// \tparam K Value type of the level (Should be unsigned integer of at least a size of 2)
template <typename I, typename N, typename K>
class directional_hqueue
{
static_assert(is_a_v<I, mln::details::Image>, "I should be an image");
static_assert(is_a_v<N, mln::details::Neighborhood>, "N should be a neighborhood");
using V = image_value_t<I>;
static_assert(std::is_invocable_v<F, V, V>, "F must be invocable with the value of I");
using Key = std::invoke_result_t<F, V, V>;
using Point = image_point_t<I>;
using queue_type = hvectors_unbounded<Point>;
......@@ -32,27 +29,27 @@ namespace mln::morpho::details
/// \param dir The hierarchical queue index (from after_offset() in N)
/// \param w The weight of the edge
/// \param p The point the edge weight is calculated from
void insert(std::size_t dir, Key w, Point p) noexcept;
void insert(std::size_t dir, int w, Point p) noexcept;
/// \brief Return the tuple (p, q, w) where p and q are the vertex of the edge and w its weight
std::tuple<Point, Point, Key> pop() noexcept;
std::tuple<Point, Point, int> pop() noexcept;
/// \brief Return the lower weight of the queue
Key current_level() const noexcept;
int current_level() const noexcept;
/// \brief Return true if the directional queue is empty
bool empty() const noexcept;
private:
static_assert(std::is_integral_v<Key> && std::is_unsigned_v<Key>, "Key should be an unsigned integral type");
static_assert(sizeof(Key) <= 2, "Key should have a size of at least 2");
static_assert(std::is_integral_v<K> && std::is_unsigned_v<K>, "Key should be an unsigned integral type");
static_assert(sizeof(K) <= 2, "Key should have a size of at least 2");
private:
static constexpr std::size_t m_ndir = decltype(N::after_offsets())::extent;
static constexpr std::size_t m_nlevels = 1 << std::numeric_limits<Key>::digits;
static constexpr int m_nlevels = 1 << std::numeric_limits<K>::digits;
std::array<std::shared_ptr<queue_type>, 2> m_queues;
std::size_t m_current_dir;
Key m_current_level;
int m_current_level;
std::size_t m_size;
};
......@@ -60,8 +57,8 @@ namespace mln::morpho::details
* Implementation *
******************/
template <typename I, typename N, typename F>
directional_hqueue<I, N, F>::directional_hqueue() noexcept
template <typename I, typename N, typename K>
directional_hqueue<I, N, K>::directional_hqueue() noexcept
: m_current_dir(0)
, m_current_level(0)
, m_size(0)
......@@ -70,8 +67,8 @@ namespace mln::morpho::details
m_queues[i] = std::make_shared<queue_type>(m_nlevels);
}
template <typename I, typename N, typename F>
void directional_hqueue<I, N, F>::insert(std::size_t dir, Key w, Point p) noexcept
template <typename I, typename N, typename K>
void directional_hqueue<I, N, K>::insert(std::size_t dir, int w, Point p) noexcept
{
// Update the current level and the current dir to keep the queue sorted
if (m_size == 0 || w < m_current_level)
......@@ -83,25 +80,24 @@ namespace mln::morpho::details
m_size++;
}
template <typename I, typename N, typename F>
std::tuple<typename directional_hqueue<I, N, F>::Point, typename directional_hqueue<I, N, F>::Point,
typename directional_hqueue<I, N, F>::Key>
directional_hqueue<I, N, F>::pop() noexcept
template <typename I, typename N, typename K>
std::tuple<typename directional_hqueue<I, N, K>::Point, typename directional_hqueue<I, N, K>::Point, int>
directional_hqueue<I, N, K>::pop() noexcept
{
assert(m_size > 0);
const auto p = m_queues[m_current_dir]->pop_front(m_current_level);
const auto q = p + N::after_offsets()[m_current_dir];
const auto w = m_current_level;
const int w = m_current_level;
m_size--;
// Update the current level and the current dir if needed
if (m_size > 0 && m_queues[m_current_dir]->empty(m_current_level))
{
std::size_t lvl = m_queues[0]->lower_bound(m_current_level);
std::size_t dir = 0;
int lvl = m_queues[0]->lower_bound(m_current_level);
int dir = 0;
for (std::size_t i = 1; i < m_ndir; i++)
{
std::size_t tmp = m_queues[i]->lower_bound(m_current_level);
int tmp = m_queues[i]->lower_bound(m_current_level);
if (tmp < lvl && tmp < m_nlevels)
{
lvl = tmp;
......@@ -115,15 +111,15 @@ namespace mln::morpho::details
return {p, q, w};
}
template <typename I, typename N, typename F>
typename directional_hqueue<I, N, F>::Key directional_hqueue<I, N, F>::current_level() const noexcept
template <typename I, typename N, typename K>
int directional_hqueue<I, N, K>::current_level() const noexcept
{
assert(m_size > 0);
return m_current_level;
}
template <typename I, typename N, typename F>
bool directional_hqueue<I, N, F>::empty() const noexcept
template <typename I, typename N, typename K>
bool directional_hqueue<I, N, K>::empty() const noexcept
{
return m_size == 0;
}
......
......@@ -22,7 +22,7 @@ TEST(Morpho, DirectionalHQueue)
constexpr std::array<W, 12> ref = {1, 2, 4, 5, 5, 8, 8, 12, 12, 17, 21, 24};
auto hqueue = mln::morpho::details::directional_hqueue<decltype(ima), mln::c4_t, F>();
auto hqueue = mln::morpho::details::directional_hqueue<decltype(ima), mln::c4_t, W>();
mln_foreach (auto p, ima.domain())
{
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment