Program Listing for File children.hpp¶
↰ Return to documentation for file (fwdpp/ts/marginal_tree_functions/children.hpp)
#ifndef FWDPP_TS_MARGINAL_TREE_FUNCTIONS_CHILDREN_HPP
#define FWDPP_TS_MARGINAL_TREE_FUNCTIONS_CHILDREN_HPP
#include "../marginal_tree.hpp"
namespace fwdpp
{
namespace ts
{
class child_iterator
{
private:
bool left_to_right;
table_index_t current_child;
std::vector<table_index_t>::const_iterator sib_begin, sib_end;
inline table_index_t
init_current_child(const marginal_tree& m, table_index_t n)
{
if (n == NULL_INDEX)
{
throw std::invalid_argument("node is NULL");
}
if (static_cast<std::size_t>(n) >= m.left_child.size())
{
throw std::invalid_argument("node id is out of range");
}
if (left_to_right)
{
return m.left_child[n];
}
return m.right_child[n];
}
public:
child_iterator(const marginal_tree& m, table_index_t n,
bool left_to_right_traversal)
: left_to_right(left_to_right_traversal),
current_child(init_current_child(m, n)),
sib_begin(left_to_right ? begin(m.right_sib)
: begin(m.left_sib)),
sib_end(left_to_right ? end(m.right_sib) : end(m.left_sib))
{
}
inline table_index_t
operator()()
{
static_assert(NULL_INDEX < 0,
"NULL_INDEX < 0 is false, so something needs to change here");
auto c = current_child;
if (c < 0)
{
return c;
}
if (sib_begin + current_child >= sib_end)
{
throw std::runtime_error("child iteration error");
}
current_child = *(sib_begin + current_child);
return c;
}
template <typename F>
inline bool
operator()(const F& f)
{
auto c = this->operator()();
bool rv = (c != NULL_INDEX);
if (rv)
{
f(c);
}
return rv;
}
};
template <typename F>
inline void
process_children(const marginal_tree& m, table_index_t n,
bool left_to_right_traversal, const F& f)
{
child_iterator ci(m, n, left_to_right_traversal);
while (ci(f))
{
}
}
inline std::vector<table_index_t>
get_children(const marginal_tree& m, table_index_t n,
bool left_to_right_traversal)
{
std::vector<table_index_t> rv;
process_children(m, n, left_to_right_traversal,
[&rv](const table_index_t c) { rv.push_back(c); });
return rv;
}
inline int
num_children(const marginal_tree& m, table_index_t n)
{
int nc = 0;
process_children(m, n, true,
[&nc](const table_index_t /*c*/) { ++nc; });
return nc;
}
} // namespace ts
} // namespace fwdpp
#endif