NTrace
GPU ray tracing framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
BinaryHeap.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2011, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #pragma once
29 #include "base/Array.hpp"
30 
31 namespace FW
32 {
33 //------------------------------------------------------------------------
34 
35 template <class T> class BinaryHeap
36 {
37 private:
38  struct Item
39  {
40  T value;
41  S32 slot; // -1 if the item does not exist
42  S32 nextInFreelist; // -1 if last, -2 if not in freelist. Freelist may contain items that are not actually free.
43  };
44 
45 public:
46  BinaryHeap (void) : m_hasBeenBuilt(false), m_freelist(-1) {}
47  BinaryHeap (const BinaryHeap<T>& other) { set(other); }
48  ~BinaryHeap (void) {}
49 
50  int numIndices (void) const { return m_items.getSize(); } // Maximum idx ever used + 1.
51  int numItems (void) const { return m_slots.getSize(); } // Actual size.
52  bool isEmpty (void) const { return (numItems() == 0); }
53  bool contains (int idx) const { return (idx >= 0 && idx < m_items.getSize() && m_items[idx].slot != -1); }
54  const T& get (int idx) const { FW_ASSERT(contains(idx)); return m_items[idx].value; }
55 
56  void clear (void) { m_items.clear(); m_slots.clear(); m_hasBeenBuilt = false; m_freelist = -1; }
57  void reset (void) { m_items.reset(); m_slots.reset(); m_hasBeenBuilt = false; m_freelist = -1; }
58  void set (const BinaryHeap<T>& other);
59  void add (int idx, const T& value); // Adds or replaces an item with the specified index.
60  int add (const T& value); // Allocates a previously unused index.
61  T remove (int idx); // Removes an item with the specified index.
62 
63  int getMinIndex (void); // Returns the index of the smallest item.
64  const T& getMin (void) { return get(getMinIndex()); } // Returns the smallest item itself.
65  int removeMinIndex(void) { int idx = getMinIndex(); remove(idx); return idx; }
66  T removeMin (void) { return remove(getMinIndex()); }
67 
68  const T& operator[] (int idx) const { return get(idx); }
69  BinaryHeap<T>& operator= (const BinaryHeap<T>& other) { set(other); return *this; }
70 
71 private:
72  bool heapify (int parentSlot);
73  void adjust (int idx, bool increased);
74 
75 private:
76  Array<Item> m_items;
77  Array<S32> m_slots;
78  bool m_hasBeenBuilt;
79  S32 m_freelist;
80 };
81 
82 //------------------------------------------------------------------------
83 
84 template <class T> void BinaryHeap<T>::set(const BinaryHeap<T>& other)
85 {
86  m_items = other.m_items;
87  m_slots = other.m_slots;
88  m_hasBeenBuilt = other.m_hasBeenBuilt;
89  m_freelist = other.m_freelist;
90 }
91 
92 //------------------------------------------------------------------------
93 
94 template <class T> void BinaryHeap<T>::add(int idx, const T& value)
95 {
96  FW_ASSERT(idx >= 0);
97 
98  // Ensure that the index exists.
99 
100  while (idx >= m_items.getSize())
101  {
102  Item& item = m_items.add();
103  item.slot = -1;
104  item.nextInFreelist = m_freelist;
105  m_freelist = m_items.getSize() - 1;
106  }
107 
108  // Replace an existing item or add a new item in the last slot.
109 
110  bool increased = false;
111  if (m_items[idx].slot != -1)
112  increased = (m_items[idx].value < value);
113  else
114  {
115  m_items[idx].slot = m_slots.getSize();
116  m_slots.add(idx);
117  }
118  m_items[idx].value = value;
119 
120  // Adjust the slot.
121 
122  if (m_hasBeenBuilt)
123  adjust(idx, increased);
124 }
125 
126 //------------------------------------------------------------------------
127 
128 template <class T> int BinaryHeap<T>::add(const T& value)
129 {
130  // Allocate an index.
131 
132  int idx;
133  do
134  {
135  idx = m_freelist;
136  if (idx == -1)
137  {
138  idx = m_items.getSize();
139  break;
140  }
141  m_freelist = m_items[idx].nextInFreelist;
142  m_items[idx].nextInFreelist = -2;
143  }
144  while (m_items[idx].slot != -1);
145 
146  // Add the item.
147 
148  add(idx, value);
149  return idx;
150 }
151 
152 //------------------------------------------------------------------------
153 
154 template <class T> T BinaryHeap<T>::remove(int idx)
155 {
156  // Not in the heap => ignore.
157 
158  if (!contains(idx))
159  return T();
160 
161  // Will have less than two slots => no need to maintain heap property.
162 
163  if (m_slots.getSize() <= 2)
164  m_hasBeenBuilt = false;
165 
166  // Remove.
167 
168  Item item = m_items[idx];
169  m_items[idx].slot = -1;
170 
171  if (item.nextInFreelist == -2)
172  {
173  m_items[idx].nextInFreelist = m_freelist;
174  m_freelist = idx;
175  }
176 
177  // Move the last item into the slot.
178 
179  int last = m_slots.removeLast();
180  if (last != idx)
181  {
182  m_items[last].slot = item.slot;
183  m_slots[item.slot] = last;
184 
185  // Adjust the slot.
186 
187  if (m_hasBeenBuilt)
188  adjust(last, (item.value < m_items[last].value));
189  }
190  return item.value;
191 }
192 
193 //------------------------------------------------------------------------
194 
195 template <class T> int BinaryHeap<T>::getMinIndex(void)
196 {
197  // Empty => ignore.
198 
199  if (isEmpty())
200  return -1;
201 
202  // Not built and has at least two slots => build now.
203 
204  if (!m_hasBeenBuilt && m_slots.getSize() >= 2)
205  {
206  for (int i = (m_slots.getSize() - 2) >> 1; i >= 0; i--)
207  {
208  int idx = m_slots[i];
209  while (heapify(m_items[idx].slot));
210  }
211  m_hasBeenBuilt = true;
212  }
213 
214  // Return the root.
215 
216  return m_slots[0];
217 }
218 
219 //------------------------------------------------------------------------
220 
221 template <class T> bool BinaryHeap<T>::heapify(int parentSlot)
222 {
223  FW_ASSERT(parentSlot >= 0 && parentSlot < m_slots.getSize());
224 
225  // Find the left-hand child.
226  // No children => done.
227 
228  int childSlot = (parentSlot << 1) + 1;
229  if (childSlot >= m_slots.getSize())
230  return false;
231 
232  int child = m_slots[childSlot];
233 
234  // Right-hand child has a smaller value => use it instead.
235 
236  if (childSlot + 1 < m_slots.getSize())
237  {
238  int other = m_slots[childSlot + 1];
239  if (m_items[other].value < m_items[child].value)
240  {
241  childSlot++;
242  child = other;
243  }
244  }
245 
246  // The parent has the smallest value => done.
247 
248  int parent = m_slots[parentSlot];
249  if (!(m_items[child].value < m_items[parent].value))
250  return false;
251 
252  /* Swap the parent and child slots. */
253 
254  m_items[child].slot = parentSlot;
255  m_items[parent].slot = childSlot;
256  m_slots[parentSlot] = child;
257  m_slots[childSlot] = parent;
258  return true;
259 }
260 
261 //------------------------------------------------------------------------
262 
263 template <class T> void BinaryHeap<T>::adjust(int idx, bool increased)
264 {
265  FW_ASSERT(contains(idx));
266  if (increased)
267  while (heapify(m_items[idx].slot));
268  else
269  while (m_items[idx].slot != 0 && heapify((m_items[idx].slot - 1) >> 1));
270 }
271 
272 //------------------------------------------------------------------------
273 }
void set(const BinaryHeap< T > &other)
Definition: BinaryHeap.hpp:84
void reset(void)
Definition: BinaryHeap.hpp:57
BinaryHeap(const BinaryHeap< T > &other)
Definition: BinaryHeap.hpp:47
const T & operator[](int idx) const
Definition: BinaryHeap.hpp:68
int numIndices(void) const
Definition: BinaryHeap.hpp:50
void clear(void)
Definition: Array.hpp:359
int numItems(void) const
Definition: BinaryHeap.hpp:51
void reset(S size=0)
Definition: Array.hpp:317
int getMinIndex(void)
Definition: BinaryHeap.hpp:195
void add(int idx, const T &value)
Definition: BinaryHeap.hpp:94
#define FW_ASSERT(X)
Definition: Defs.hpp:67
signed int S32
Definition: Defs.hpp:88
bool contains(int idx) const
Definition: BinaryHeap.hpp:53
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value
Definition: DLLImports.inl:84
int removeMinIndex(void)
Definition: BinaryHeap.hpp:65
bool isEmpty(void) const
Definition: BinaryHeap.hpp:52
BinaryHeap< T > & operator=(const BinaryHeap< T > &other)
Definition: BinaryHeap.hpp:69
const T & getMin(void)
Definition: BinaryHeap.hpp:64
void clear(void)
Definition: BinaryHeap.hpp:56
T remove(int idx)
Definition: BinaryHeap.hpp:154
S getSize(void) const
Definition: Array.hpp:188
T removeMin(void)
Definition: BinaryHeap.hpp:66