Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Core/BinaryHeap.h
9906 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
JPH_NAMESPACE_BEGIN
8
9
/// Push a new element into a binary max-heap.
10
/// [inBegin, inEnd - 1) must be a a valid heap. Element inEnd - 1 will be inserted into the heap. The heap will be [inBegin, inEnd) after this call.
11
/// inPred is a function that returns true if the first element is less or equal than the second element.
12
/// See: https://en.wikipedia.org/wiki/Binary_heap
13
template <typename Iterator, typename Pred>
14
void BinaryHeapPush(Iterator inBegin, Iterator inEnd, Pred inPred)
15
{
16
using diff_t = typename std::iterator_traits<Iterator>::difference_type;
17
using elem_t = typename std::iterator_traits<Iterator>::value_type;
18
19
// New heap size
20
diff_t count = std::distance(inBegin, inEnd);
21
22
// Start from the last element
23
diff_t current = count - 1;
24
while (current > 0)
25
{
26
// Get current element
27
elem_t &current_elem = *(inBegin + current);
28
29
// Get parent element
30
diff_t parent = (current - 1) >> 1;
31
elem_t &parent_elem = *(inBegin + parent);
32
33
// Sort them so that the parent is larger than the child
34
if (inPred(parent_elem, current_elem))
35
{
36
std::swap(parent_elem, current_elem);
37
current = parent;
38
}
39
else
40
{
41
// When there's no change, we're done
42
break;
43
}
44
}
45
}
46
47
/// Pop an element from a binary max-heap.
48
/// [inBegin, inEnd) must be a valid heap. The largest element will be removed from the heap. The heap will be [inBegin, inEnd - 1) after this call.
49
/// inPred is a function that returns true if the first element is less or equal than the second element.
50
/// See: https://en.wikipedia.org/wiki/Binary_heap
51
template <typename Iterator, typename Pred>
52
void BinaryHeapPop(Iterator inBegin, Iterator inEnd, Pred inPred)
53
{
54
using diff_t = typename std::iterator_traits<Iterator>::difference_type;
55
56
// Begin by moving the highest element to the end, this is the popped element
57
std::swap(*(inEnd - 1), *inBegin);
58
59
// New heap size
60
diff_t count = std::distance(inBegin, inEnd) - 1;
61
62
// Start from the root
63
diff_t largest = 0;
64
for (;;)
65
{
66
// Get first child
67
diff_t child = (largest << 1) + 1;
68
69
// Check if we're beyond the end of the heap, if so the 2nd child is also beyond the end
70
if (child >= count)
71
break;
72
73
// Remember the largest element from the previous iteration
74
diff_t prev_largest = largest;
75
76
// Check if first child is bigger, if so select it
77
if (inPred(*(inBegin + largest), *(inBegin + child)))
78
largest = child;
79
80
// Switch to the second child
81
++child;
82
83
// Check if second child is bigger, if so select it
84
if (child < count && inPred(*(inBegin + largest), *(inBegin + child)))
85
largest = child;
86
87
// If there was no change, we're done
88
if (prev_largest == largest)
89
break;
90
91
// Swap element
92
std::swap(*(inBegin + prev_largest), *(inBegin + largest));
93
}
94
}
95
96
JPH_NAMESPACE_END
97
98