24 template <
typename IntegerType>
27 template <
typename IntegerType>
30 return {
std::max(right.envelope, left.envelope + right.sum_of_energy_min),
32 right.sum_of_energy_min +
34 left.envelope + right.max_of_energy_delta)),
35 left.sum_of_energy_min + right.sum_of_energy_min,
36 std::max(right.max_of_energy_delta, left.max_of_energy_delta)};
39 template <
typename IntegerType>
42 leaf_nodes_have_delayed_operations_ =
false;
47 num_events_ = num_events;
48 num_leaves_ =
std::max(2, num_events + (num_events & 1));
50 const int num_nodes = 2 * num_leaves_;
51 tree_.assign(num_nodes, TreeNode{IntegerTypeMinimumValue<IntegerType>(),
52 IntegerTypeMinimumValue<IntegerType>(),
53 IntegerType{0}, IntegerType{0}});
59 for (power_of_two_ = 2; power_of_two_ < num_leaves_; power_of_two_ <<= 1) {
63 template <
typename IntegerType>
70 const int r = power_of_two_ + event;
71 return r < 2 * num_leaves_ ? r : r - num_leaves_;
74 template <
typename IntegerType>
75 int ThetaLambdaTree<IntegerType>::GetEventFromLeaf(
int leaf)
const {
78 const int r = leaf - power_of_two_;
79 return r >= 0 ? r : r + num_leaves_;
82 template <
typename IntegerType>
85 leaf_nodes_have_delayed_operations_ =
false;
88 const int last_internal_node = tree_.size() / 2 - 1;
89 for (
int node = last_internal_node; node >= 1; --node) {
90 const int right = 2 * node + 1;
91 const int left = 2 * node;
92 tree_[node] = ComposeTreeNodes(tree_[left], tree_[right]);
96 template <
typename IntegerType>
98 int event, IntegerType initial_envelope, IntegerType energy_min,
99 IntegerType energy_max) {
101 leaf_nodes_have_delayed_operations_ =
true;
105 const int node = GetLeafFromEvent(event);
106 tree_[node] = {initial_envelope + energy_min, initial_envelope + energy_max,
107 energy_min, energy_max - energy_min};
110 template <
typename IntegerType>
112 int event, IntegerType initial_envelope, IntegerType energy_min,
113 IntegerType energy_max) {
114 DCHECK(!leaf_nodes_have_delayed_operations_);
117 const int node = GetLeafFromEvent(event);
118 tree_[node] = {initial_envelope + energy_min, initial_envelope + energy_max,
119 energy_min, energy_max - energy_min};
123 template <
typename IntegerType>
125 int event, IntegerType initial_envelope_opt, IntegerType energy_max) {
126 DCHECK(!leaf_nodes_have_delayed_operations_);
128 const int node = GetLeafFromEvent(event);
129 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
130 initial_envelope_opt + energy_max, IntegerType{0}, energy_max};
134 template <
typename IntegerType>
136 int event, IntegerType initial_envelope_opt, IntegerType energy_max) {
138 leaf_nodes_have_delayed_operations_ =
true;
141 const int node = GetLeafFromEvent(event);
142 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
143 initial_envelope_opt + energy_max, IntegerType{0}, energy_max};
146 template <
typename IntegerType>
148 DCHECK(!leaf_nodes_have_delayed_operations_);
149 const int node = GetLeafFromEvent(event);
150 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
151 IntegerTypeMinimumValue<IntegerType>(), IntegerType{0},
156 template <
typename IntegerType>
159 leaf_nodes_have_delayed_operations_ =
true;
161 const int node = GetLeafFromEvent(event);
162 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
163 IntegerTypeMinimumValue<IntegerType>(), IntegerType{0},
167 template <
typename IntegerType>
169 DCHECK(!leaf_nodes_have_delayed_operations_);
170 return tree_[1].envelope;
172 template <
typename IntegerType>
174 DCHECK(!leaf_nodes_have_delayed_operations_);
175 return tree_[1].envelope_opt;
178 template <
typename IntegerType>
180 IntegerType target_envelope)
const {
181 DCHECK(!leaf_nodes_have_delayed_operations_);
182 DCHECK_LT(target_envelope, tree_[1].envelope);
184 return GetEventFromLeaf(
185 GetMaxLeafWithEnvelopeGreaterThan(1, target_envelope, &unused));
188 template <
typename IntegerType>
190 IntegerType target_envelope,
int* critical_event,
int* optional_event,
191 IntegerType* available_energy)
const {
192 DCHECK(!leaf_nodes_have_delayed_operations_);
195 GetLeavesWithOptionalEnvelopeGreaterThan(target_envelope, &critical_leaf,
196 &optional_leaf, available_energy);
197 *critical_event = GetEventFromLeaf(critical_leaf);
198 *optional_event = GetEventFromLeaf(optional_leaf);
201 template <
typename IntegerType>
203 DCHECK(!leaf_nodes_have_delayed_operations_);
204 const int leaf = GetLeafFromEvent(event);
205 IntegerType envelope = tree_[leaf].envelope;
206 for (
int node = leaf; node > 1; node >>= 1) {
207 const int right = node | 1;
208 if (node != right) envelope += tree_[right].sum_of_energy_min;
213 template <
typename IntegerType>
216 const int right = node | 1;
217 const int left = right ^ 1;
219 tree_[node] = ComposeTreeNodes(tree_[left], tree_[right]);
223 template <
typename IntegerType>
224 int ThetaLambdaTree<IntegerType>::GetMaxLeafWithEnvelopeGreaterThan(
225 int node, IntegerType target_envelope, IntegerType* extra)
const {
226 DCHECK(!leaf_nodes_have_delayed_operations_);
227 DCHECK_LT(target_envelope, tree_[node].envelope);
228 while (node < num_leaves_) {
229 const int left = node << 1;
230 const int right = left | 1;
233 if (target_envelope < tree_[right].envelope) {
236 target_envelope -= tree_[right].sum_of_energy_min;
240 *extra = tree_[node].envelope - target_envelope;
244 template <
typename IntegerType>
245 int ThetaLambdaTree<IntegerType>::GetLeafWithMaxEnergyDelta(
int node)
const {
246 DCHECK(!leaf_nodes_have_delayed_operations_);
247 const IntegerType delta_node = tree_[node].max_of_energy_delta;
248 while (node < num_leaves_) {
249 const int left = node << 1;
250 const int right = left | 1;
252 if (tree_[right].max_of_energy_delta == delta_node) {
255 DCHECK_EQ(tree_[left].max_of_energy_delta, delta_node);
262 template <
typename IntegerType>
263 void ThetaLambdaTree<IntegerType>::GetLeavesWithOptionalEnvelopeGreaterThan(
264 IntegerType target_envelope,
int* critical_leaf,
int* optional_leaf,
265 IntegerType* available_energy)
const {
266 DCHECK(!leaf_nodes_have_delayed_operations_);
267 DCHECK_LT(target_envelope, tree_[1].envelope_opt);
269 while (node < num_leaves_) {
270 const int left = node << 1;
271 const int right = left | 1;
274 if (target_envelope < tree_[right].envelope_opt) {
277 const IntegerType opt_energy_right =
278 tree_[right].sum_of_energy_min + tree_[right].max_of_energy_delta;
279 if (target_envelope < tree_[left].envelope + opt_energy_right) {
280 *optional_leaf = GetLeafWithMaxEnergyDelta(right);
282 *critical_leaf = GetMaxLeafWithEnvelopeGreaterThan(
283 left, target_envelope - opt_energy_right, &extra);
284 *available_energy = tree_[*optional_leaf].sum_of_energy_min +
285 tree_[*optional_leaf].max_of_energy_delta - extra;
288 target_envelope -= tree_[right].sum_of_energy_min;
293 *critical_leaf = node;
294 *optional_leaf = node;
295 *available_energy = target_envelope - (tree_[node].envelope_opt -
296 tree_[node].sum_of_energy_min -
297 tree_[node].max_of_energy_delta);
300 template class ThetaLambdaTree<IntegerValue>;
301 template class ThetaLambdaTree<int64>;