File: clamped_uint.cpp

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 (105 lines) | stat: -rw-r--r-- 3,009 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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <terraces/clamped_uint.hpp>

#include <ostream>
#include <terraces/errors.hpp>

#include "intrinsics.hpp"
#include "utils.hpp"

namespace terraces {

namespace {
static constexpr auto max_index = std::numeric_limits<index>::max();
}

template <bool except>
checked_uint<except>::checked_uint(index value) : m_value{value} {}

// clamped version
template <>
checked_uint<false>& checked_uint<false>::operator+=(checked_uint<false> other) {
	if (bits::add_overflow(m_value, other.m_value, m_value)) {
		m_value = max_index;
	}
	return *this;
}

template <>
checked_uint<false>& checked_uint<false>::operator*=(checked_uint<false> other) {
	if (bits::mul_overflow(m_value, other.m_value, m_value)) {
		m_value = max_index;
	}
	return *this;
}

template <>
checked_uint<true>& checked_uint<true>::operator+=(checked_uint<true> other) {
	utils::ensure<tree_count_overflow_error>(
	        !bits::add_overflow(m_value, other.m_value, m_value), "Addition overflowed");
	return *this;
}

template <>
checked_uint<true>& checked_uint<true>::operator*=(checked_uint<true> other) {
	utils::ensure<tree_count_overflow_error>(
	        !bits::mul_overflow(m_value, other.m_value, m_value), "Multiplication overflowed");
	return *this;
}

template <bool except>
bool checked_uint<except>::is_clamped() const {
	return m_value == max_index;
}

template <bool except>
index checked_uint<except>::value() const {
	return m_value;
}

template <bool except>
bool operator==(checked_uint<except> a, checked_uint<except> b) {
	return a.value() == b.value();
}

template <bool except>
bool operator!=(checked_uint<except> a, checked_uint<except> b) {
	return !(a == b);
}

template <bool except>
checked_uint<except> operator+(checked_uint<except> a, checked_uint<except> b) {
	return a += b;
}

template <bool except>
checked_uint<except> operator*(checked_uint<except> a, checked_uint<except> b) {
	return a *= b;
}

template <bool except>
std::ostream& operator<<(std::ostream& stream, checked_uint<except> val) {
	if (val.is_clamped()) {
		stream << ">= ";
	}
	stream << val.value();
	return stream;
}

// explicitly instantiate template class
template class checked_uint<false>;
template class checked_uint<true>;

// explicitly instantiate template functions
template bool operator==(checked_uint<false>, checked_uint<false>);
template bool operator!=(checked_uint<false>, checked_uint<false>);
template checked_uint<false> operator+(checked_uint<false>, checked_uint<false>);
template checked_uint<false> operator*(checked_uint<false>, checked_uint<false>);
template std::ostream& operator<<(std::ostream&, checked_uint<false>);

template bool operator==(checked_uint<true>, checked_uint<true>);
template bool operator!=(checked_uint<true>, checked_uint<true>);
template checked_uint<true> operator+(checked_uint<true>, checked_uint<true>);
template checked_uint<true> operator*(checked_uint<true>, checked_uint<true>);
template std::ostream& operator<<(std::ostream&, checked_uint<true>);

} // namespace terraces