File: small_bipartition.hpp

package info (click to toggle)
iqtree 2.0.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 14,620 kB
  • sloc: cpp: 142,571; ansic: 57,789; sh: 275; python: 242; makefile: 95
file content (53 lines) | stat: -rw-r--r-- 1,384 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef UNCONSTRAINED_ENUMERATOR_CPP
#define UNCONSTRAINED_ENUMERATOR_CPP

#include "multitree.hpp"

#include <bitset>
#include <cassert>
#include <vector>

#include "bits.hpp"

namespace terraces {

using bits::bitscan;
using bits::rbitscan;
using bits::popcount;

struct small_bipartition {
	index m_mask;
	index m_cur_bip;

	small_bipartition(index mask = 1) : m_mask{mask} { reset(); }

	// credit goes to nglee
	// (see stackoverflow.com/questions/44767080/incrementing-masked-bitsets)
	index masked_increment(index bip) const { return -(bip ^ m_mask) & m_mask; }

	bool has_choices() const { return num_leaves() > 2; }

	bool is_valid() const { return (m_cur_bip >> rbitscan(m_mask)) == 0; }

	bool next() {
		assert(is_valid());
		m_cur_bip = masked_increment(m_cur_bip);
		return is_valid();
	}
	void reset() { m_cur_bip = index(1) << bitscan(m_mask); }

	index mask() const { return m_mask; }
	index left_mask() const { return m_cur_bip; }
	index right_mask() const { return m_cur_bip ^ m_mask; }
	index leftmost_leaf() const { return bitscan(m_mask); }
	index rightmost_leaf() const { return rbitscan(m_mask); }
	index num_leaves() const { return popcount(m_mask); }

	static small_bipartition full_set(index num_leaves) {
		assert(num_leaves < bits::word_bits);
		return {(index(1) << num_leaves) - 1};
	}
};
} // namespace terraces

#endif // UNCONSTRAINED_ENUMERATOR_CPP