NvHashMap.h 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905
  1. /*
  2. NvHashMap.h : A simple hash map and array template class to avoid introducing dependencies on the STL for containers.
  3. */
  4. // This code contains NVIDIA Confidential Information and is disclosed
  5. // under the Mutual Non-Disclosure Agreement.
  6. //
  7. // Notice
  8. // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
  9. // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
  10. // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
  11. // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
  12. //
  13. // Information and code furnished is believed to be accurate and reliable.
  14. // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
  15. // information or for any infringement of patents or other rights of third parties that may
  16. // result from its use. No license is granted by implication or otherwise under any patent
  17. // or patent rights of NVIDIA Corporation. Details are subject to change without notice.
  18. // This code supersedes and replaces all information previously supplied.
  19. // NVIDIA Corporation products are not authorized for use as critical
  20. // components in life support devices or systems without express written approval of
  21. // NVIDIA Corporation.
  22. //
  23. // Copyright � 2009 NVIDIA Corporation. All rights reserved.
  24. // Copyright � 2002-2008 AGEIA Technologies, Inc. All rights reserved.
  25. // Copyright � 2001-2006 NovodeX. All rights reserved.
  26. #ifndef NV_HASH_MAP_H
  27. #define NV_HASH_MAP_H
  28. #include "NvUserMemAlloc.h"
  29. #if (defined(NX_WINDOWS) | defined(NX_X360))
  30. #include <typeinfo.h>
  31. #endif
  32. #include <new>
  33. #include <typeinfo>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. //******************************************************
  37. //******************************************************
  38. //******************************************************
  39. #ifndef NV_FOUNDATION_BASIC_TEMPLATES_H
  40. #define NV_FOUNDATION_BASIC_TEMPLATES_H
  41. #pragma warning(push)
  42. #pragma warning(disable:4512) // suppress the 'assignment operator could not be generated' warning message.
  43. namespace CONVEX_DECOMPOSITION
  44. {
  45. template<typename A>
  46. struct Equal
  47. {
  48. bool operator()(const A& a, const A& b) const { return a==b; }
  49. };
  50. template<typename A>
  51. struct Less
  52. {
  53. bool operator()(const A& a, const A& b) const { return a<b; }
  54. };
  55. template<typename A>
  56. struct Greater
  57. {
  58. bool operator()(const A& a, const A& b) const { return a>b; }
  59. };
  60. template <class F, class S>
  61. class Pair
  62. {
  63. public:
  64. F first;
  65. S second;
  66. Pair(): first(F()), second(S()) {}
  67. Pair(const F &f, const S &s): first(f), second(s) {}
  68. Pair(const Pair &p): first(p.first), second(p.second) {}
  69. };
  70. template<unsigned int A> struct LogTwo { static const unsigned int value = LogTwo<(A>>1)>::value + 1; };
  71. template<> struct LogTwo<1>{ static const unsigned int value = 0; };
  72. template<typename T> struct UnConst { typedef T Type; };
  73. template<typename T> struct UnConst<const T> { typedef T Type; };
  74. }
  75. #pragma warning(pop)
  76. #endif
  77. #ifndef NV_FOUNDATION_ALLOCATOR
  78. #define NV_FOUNDATION_ALLOCATOR
  79. #pragma warning(push)
  80. #pragma warning(disable:4100)
  81. namespace CONVEX_DECOMPOSITION
  82. {
  83. /**
  84. \brief The return value is the greater of the two specified values.
  85. */
  86. template<class N>
  87. NX_INLINE N NxMax(N a, N b) { return a<b ? b : a; }
  88. /**
  89. \brief The return value is the greater of the two specified values.
  90. */
  91. template <>
  92. NX_INLINE NxF32 NxMax(NxF32 a, NxF32 b) { return a > b ? a : b; }
  93. /**
  94. \brief The return value is the lesser of the two specified values.
  95. */
  96. template<class N>
  97. NX_INLINE N NxMin(N a, N b) { return a<b ? a : b; }
  98. /**
  99. \brief The return value is the lesser of the two specified values.
  100. */
  101. template <>
  102. NX_INLINE NxF32 NxMin(NxF32 a, NxF32 b) { return a < b ? a : b; }
  103. /**
  104. Allocator used to access the global NxUserAllocator instance without providing additional information.
  105. */
  106. class Allocator
  107. {
  108. public:
  109. Allocator(const char* dummy = 0)
  110. {
  111. }
  112. void* allocate(size_t size, const char* file, int line)
  113. {
  114. return MEMALLOC_MALLOC(size);
  115. }
  116. void deallocate(void* ptr)
  117. {
  118. MEMALLOC_FREE(ptr);
  119. }
  120. };
  121. /**
  122. Allocator used to access the global NxUserAllocator instance using a dynamic name.
  123. */
  124. class NamedAllocator
  125. {
  126. public:
  127. NamedAllocator(const char* name = 0)
  128. {
  129. }
  130. void* allocate(size_t size, const char* filename, int line)
  131. {
  132. return MEMALLOC_MALLOC(size);
  133. }
  134. void deallocate(void* ptr)
  135. {
  136. MEMALLOC_FREE(ptr);
  137. }
  138. private:
  139. };
  140. /**
  141. Allocator used to access the global NxUserAllocator instance using a static name derived from T.
  142. */
  143. template <typename T>
  144. class ReflectionAllocator
  145. {
  146. static const char* getName()
  147. {
  148. #if defined NX_GNUC
  149. return __PRETTY_FUNCTION__;
  150. #else
  151. return typeid(T).name();
  152. #endif
  153. }
  154. public:
  155. ReflectionAllocator(const char* dummy=0)
  156. {
  157. }
  158. void* allocate(size_t size, const char* filename, int line)
  159. {
  160. return MEMALLOC_MALLOC(size);
  161. }
  162. void deallocate(void* ptr)
  163. {
  164. MEMALLOC_FREE(ptr);
  165. }
  166. };
  167. // if you get a build error here, you are trying to NX_NEW a class
  168. // that is neither plain-old-type nor derived from CONVEX_DECOMPOSITION::UserAllocated
  169. template <typename T, typename X>
  170. union EnableIfPod
  171. {
  172. int i; T t;
  173. typedef X Type;
  174. };
  175. }
  176. // Global placement new for ReflectionAllocator templated by plain-old-type. Allows using NX_NEW for pointers and built-in-types.
  177. // ATTENTION: You need to use NX_DELETE_POD or NX_FREE to deallocate memory, not NX_DELETE. NX_DELETE_POD redirects to NX_FREE.
  178. // Rationale: NX_DELETE uses global operator delete(void*), which we dont' want to overload.
  179. // Any other definition of NX_DELETE couldn't support array syntax 'NX_DELETE([]a);'.
  180. // NX_DELETE_POD was preferred over NX_DELETE_ARRAY because it is used less often and applies to both single instances and arrays.
  181. template <typename T>
  182. NX_INLINE void* operator new(size_t size, CONVEX_DECOMPOSITION::ReflectionAllocator<T> alloc, const char* fileName, typename CONVEX_DECOMPOSITION::EnableIfPod<T, int>::Type line)
  183. {
  184. return alloc.allocate(size, fileName, line);
  185. }
  186. template <typename T>
  187. NX_INLINE void* operator new[](size_t size, CONVEX_DECOMPOSITION::ReflectionAllocator<T> alloc, const char* fileName, typename CONVEX_DECOMPOSITION::EnableIfPod<T, int>::Type line)
  188. {
  189. return alloc.allocate(size, fileName, line);
  190. }
  191. // If construction after placement new throws, this placement delete is being called.
  192. template <typename T>
  193. NX_INLINE void operator delete(void* ptr, CONVEX_DECOMPOSITION::ReflectionAllocator<T> alloc, const char* fileName, typename CONVEX_DECOMPOSITION::EnableIfPod<T, int>::Type line)
  194. {
  195. alloc.deallocate(ptr);
  196. }
  197. // If construction after placement new throws, this placement delete is being called.
  198. template <typename T>
  199. NX_INLINE void operator delete[](void* ptr, CONVEX_DECOMPOSITION::ReflectionAllocator<T> alloc, const char* fileName, typename CONVEX_DECOMPOSITION::EnableIfPod<T, int>::Type line)
  200. {
  201. alloc.deallocate(ptr);
  202. }
  203. #pragma warning(pop)
  204. #endif
  205. #ifndef NV_FOUNDATION_USERALLOCATED
  206. #define NV_FOUNDATION_USERALLOCATED
  207. // an expression that should expand to nothing in _DEBUG builds. We currently
  208. // use this only for tagging the purpose of containers for memory use tracking.
  209. #if defined(_DEBUG)
  210. #define NV_DEBUG_EXP(x) (x)
  211. #define NV_DEBUG_EXP_C(x) x,
  212. #else
  213. #define NV_DEBUG_EXP(x)
  214. #define NV_DEBUG_EXP_C(x)
  215. #endif
  216. #if defined (NX_X360) | defined (NX_WINDOWS) | defined (NX_CELL) | defined (NXLINUX) | defined(NX_WII)
  217. // Stack allocation with alloc fallback for large allocations (>50% of default stack size for platform)
  218. # define NX_ALLOCA(var, type, number) \
  219. bool alloced_##var = false; \
  220. if (sizeof(type)*number*2 > (CONVEX_DECOMPOSITION::gSystemServices ? gSystemServices->getAllocaThreshold() : 8192) ) \
  221. { \
  222. var = (type *)MEMALLOC_MALLOC(sizeof(type)*number); \
  223. alloced_##var = true; \
  224. } else { \
  225. var = (type *)MEMALLOC_ALLOCA(sizeof(type)*number); \
  226. }
  227. # define NX_FREEA(var) if (alloced_##var) MEMALLOC_FREE(var);
  228. #else
  229. # define NX_ALLOCA(var, type, number) var = (type *)NxAlloca(sizeof(type)*number);
  230. # define NX_FREEA(var) 0;
  231. #endif
  232. namespace CONVEX_DECOMPOSITION
  233. {
  234. /**
  235. Provides new and delete using a UserAllocator.
  236. Guarantees that 'delete x;' uses the UserAllocator too.
  237. */
  238. class UserAllocated
  239. {
  240. public:
  241. template <typename Alloc>
  242. NX_INLINE void* operator new(size_t size, Alloc alloc, const char* fileName, int line)
  243. {
  244. return MEMALLOC_MALLOC(size);
  245. }
  246. template <typename Alloc>
  247. NX_INLINE void* operator new[](size_t size, Alloc alloc, const char* fileName, int line)
  248. {
  249. return MEMALLOC_MALLOC(size);
  250. }
  251. NX_INLINE void operator delete(void* ptr)
  252. {
  253. MEMALLOC_FREE(ptr);
  254. }
  255. NX_INLINE void operator delete[](void* ptr)
  256. {
  257. MEMALLOC_FREE(ptr);
  258. }
  259. };
  260. };
  261. #endif
  262. #ifndef NV_FOUNDATION_ALIGNEDMALLOC_H
  263. #define NV_FOUNDATION_ALIGNEDMALLOC_H
  264. /*!
  265. Allocate aligned memory.
  266. Alignment must be a power of 2!
  267. -- should be templated by a base allocator
  268. */
  269. namespace CONVEX_DECOMPOSITION
  270. {
  271. /**
  272. Allocator, which is used to access the global NxUserAllocator instance
  273. (used for dynamic data types template instantiation), which can align memory
  274. */
  275. // SCS: AlignedMalloc with 3 params not found, seems not used on PC either
  276. // disabled for now to avoid GCC error
  277. template<NxU32 N, typename BaseAllocator = Allocator >
  278. class AlignedAllocator : public BaseAllocator
  279. {
  280. public:
  281. AlignedAllocator(const BaseAllocator& base = BaseAllocator())
  282. : BaseAllocator(base) {}
  283. void* allocate(size_t size, const char* file, int line)
  284. {
  285. size_t pad = N - 1 + sizeof(size_t); // store offset for delete.
  286. NxU8* base = (NxU8*)BaseAllocator::allocate(size+pad, file, line);
  287. NxU8* ptr = (NxU8*)(size_t(base + pad) & ~(N - 1)); // aligned pointer
  288. ((size_t*)ptr)[-1] = ptr - base; // store offset
  289. return ptr;
  290. }
  291. void deallocate(void* ptr)
  292. {
  293. if(ptr == NULL)
  294. return;
  295. NxU8* base = ((NxU8*)ptr) - ((size_t*)ptr)[-1];
  296. BaseAllocator::deallocate(base);
  297. }
  298. };
  299. }
  300. #endif
  301. #ifndef NV_FOUNDATION_INLINE_ALLOCATOR_H
  302. #define NV_FOUNDATION_INLINE_ALLOCATOR_H
  303. namespace CONVEX_DECOMPOSITION
  304. {
  305. // this is used by the array class to allocate some space for a small number
  306. // of objects along with the metadata
  307. template<NxU32 N, typename BaseAllocator>
  308. class InlineAllocator : private BaseAllocator
  309. {
  310. public:
  311. InlineAllocator(const BaseAllocator& alloc = BaseAllocator())
  312. : BaseAllocator(alloc)
  313. {}
  314. void* allocate(size_t size, const char* filename, int line)
  315. {
  316. return size <= N ? mBuffer : BaseAllocator::allocate(size, filename, line);
  317. }
  318. void deallocate(void* ptr)
  319. {
  320. if(ptr != mBuffer)
  321. BaseAllocator::deallocate(ptr);
  322. }
  323. private:
  324. NxU8 mBuffer[N];
  325. };
  326. }
  327. #endif
  328. #ifndef NV_FOUNDATION_NXSTRIDEDDATA
  329. #define NV_FOUNDATION_NXSTRIDEDDATA
  330. /** \addtogroup foundation
  331. @{
  332. */
  333. template<typename T>
  334. class NvStrideIterator
  335. {
  336. template <typename X>
  337. struct StripConst
  338. {
  339. typedef X Type;
  340. };
  341. template <typename X>
  342. struct StripConst<const X>
  343. {
  344. typedef X Type;
  345. };
  346. public:
  347. explicit NX_INLINE NvStrideIterator(T* ptr = NULL, NxU32 stride = sizeof(T)) :
  348. mPtr(ptr), mStride(stride)
  349. {
  350. NX_ASSERT(mStride == 0 || sizeof(T) <= mStride);
  351. }
  352. NX_INLINE NvStrideIterator(const NvStrideIterator<typename StripConst<T>::Type>& strideIterator) :
  353. mPtr(strideIterator.ptr()), mStride(strideIterator.stride())
  354. {
  355. NX_ASSERT(mStride == 0 || sizeof(T) <= mStride);
  356. }
  357. NX_INLINE T* ptr() const
  358. {
  359. return mPtr;
  360. }
  361. NX_INLINE NxU32 stride() const
  362. {
  363. return mStride;
  364. }
  365. NX_INLINE T& operator*() const
  366. {
  367. return *mPtr;
  368. }
  369. NX_INLINE T* operator->() const
  370. {
  371. return mPtr;
  372. }
  373. NX_INLINE T& operator[](int i) const
  374. {
  375. return *byteAdd(mPtr, i * stride());
  376. }
  377. // preincrement
  378. NX_INLINE NvStrideIterator& operator++()
  379. {
  380. mPtr = byteAdd(mPtr, stride());
  381. return *this;
  382. }
  383. // postincrement
  384. NX_INLINE NvStrideIterator operator++(int)
  385. {
  386. NvStrideIterator tmp = *this;
  387. mPtr = byteAdd(mPtr, stride());
  388. return tmp;
  389. }
  390. // predecrement
  391. NX_INLINE NvStrideIterator& operator--()
  392. {
  393. mPtr = byteSub(mPtr, stride());
  394. return *this;
  395. }
  396. // postdecrement
  397. NX_INLINE NvStrideIterator operator--(int)
  398. {
  399. NvStrideIterator tmp = *this;
  400. mPtr = byteSub(mPtr, stride());
  401. return tmp;
  402. }
  403. NX_INLINE NvStrideIterator& operator+=(int i)
  404. {
  405. mPtr = byteAdd(mPtr, i * stride());
  406. return *this;
  407. }
  408. NX_INLINE NvStrideIterator operator+(int i) const
  409. {
  410. return NvStrideIterator(byteAdd(mPtr, i * stride()), stride());
  411. }
  412. NX_INLINE NvStrideIterator& operator-=(int i)
  413. {
  414. mPtr = byteSub(mPtr, i * stride());
  415. return *this;
  416. }
  417. NX_INLINE NvStrideIterator operator-(int i) const
  418. {
  419. return NvStrideIterator(byteSub(mPtr, i * stride()), stride());
  420. }
  421. // iterator difference
  422. NX_INLINE int operator-(const NvStrideIterator& other) const
  423. {
  424. NX_ASSERT(isCompatible(other));
  425. int byteDiff = static_cast<int>(reinterpret_cast<const NxU8*>(mPtr) - reinterpret_cast<const NxU8*>(other.mPtr));
  426. return byteDiff / static_cast<int>(stride());
  427. }
  428. NX_INLINE bool operator==(const NvStrideIterator& other) const
  429. {
  430. NX_ASSERT(isCompatible(other));
  431. return mPtr == other.mPtr;
  432. }
  433. NX_INLINE bool operator!=(const NvStrideIterator& other) const
  434. {
  435. NX_ASSERT(isCompatible(other));
  436. return mPtr != other.mPtr;
  437. }
  438. NX_INLINE bool operator<(const NvStrideIterator& other) const
  439. {
  440. NX_ASSERT(isCompatible(other));
  441. return mPtr < other.mPtr;
  442. }
  443. NX_INLINE bool operator>(const NvStrideIterator& other) const
  444. {
  445. NX_ASSERT(isCompatible(other));
  446. return mPtr > other.mPtr;
  447. }
  448. NX_INLINE bool operator<=(const NvStrideIterator& other) const
  449. {
  450. NX_ASSERT(isCompatible(other));
  451. return mPtr <= other.mPtr;
  452. }
  453. NX_INLINE bool operator>=(const NvStrideIterator& other) const
  454. {
  455. NX_ASSERT(isCompatible(other));
  456. return mPtr >= other.mPtr;
  457. }
  458. private:
  459. NX_INLINE static T* byteAdd(T* ptr, NxU32 bytes)
  460. {
  461. return const_cast<T*>(reinterpret_cast<const T*>(reinterpret_cast<const NxU8*>(ptr) + bytes));
  462. }
  463. NX_INLINE static T* byteSub(T* ptr, NxU32 bytes)
  464. {
  465. return const_cast<T*>(reinterpret_cast<const T*>(reinterpret_cast<const NxU8*>(ptr) - bytes));
  466. }
  467. NX_INLINE bool isCompatible(const NvStrideIterator& other) const
  468. {
  469. int byteDiff = static_cast<int>(reinterpret_cast<const NxU8*>(mPtr) - reinterpret_cast<const NxU8*>(other.mPtr));
  470. return (stride() == other.stride()) && (abs(byteDiff) % stride() == 0);
  471. }
  472. T* mPtr;
  473. NxU32 mStride;
  474. };
  475. template<typename T>
  476. NX_INLINE NvStrideIterator<T> operator+(int i, NvStrideIterator<T> it)
  477. {
  478. it += i;
  479. return it;
  480. }
  481. /** @} */
  482. #endif
  483. #ifndef NV_FOUNDATION_ARRAY
  484. #define NV_FOUNDATION_ARRAY
  485. namespace CONVEX_DECOMPOSITION
  486. {
  487. namespace Internal
  488. {
  489. template <typename T>
  490. struct ArrayMetaData
  491. {
  492. T* mData;
  493. NxU32 mCapacity;
  494. NxU32 mSize;
  495. ArrayMetaData(): mSize(0), mCapacity(0), mData(0) {}
  496. };
  497. template <typename T>
  498. struct AllocatorTraits
  499. {
  500. #if defined _DEBUG
  501. typedef NamedAllocator Type;
  502. #else
  503. typedef ReflectionAllocator<T> Type;
  504. #endif
  505. };
  506. }
  507. /*!
  508. An array is a sequential container.
  509. Implementation note
  510. * entries between 0 and size are valid objects
  511. * we use inheritance to build this because the array is included inline in a lot
  512. of objects and we want the allocator to take no space if it's not stateful, which
  513. aggregation doesn't allow. Also, we want the metadata at the front for the inline
  514. case where the allocator contains some inline storage space
  515. */
  516. template<class T, class Alloc = typename Internal::AllocatorTraits<T>::Type >
  517. class Array : private Internal::ArrayMetaData<T>, private Alloc
  518. {
  519. typedef Internal::ArrayMetaData<T> MetaData;
  520. using MetaData::mCapacity;
  521. using MetaData::mData;
  522. using MetaData::mSize;
  523. public:
  524. typedef T* Iterator;
  525. typedef const T* ConstIterator;
  526. /*!
  527. Default array constructor. Initialize an empty array
  528. */
  529. NX_INLINE Array(const Alloc& alloc = Alloc()) : Alloc(alloc) {}
  530. /*!
  531. Initialize array with given length
  532. */
  533. NX_INLINE explicit Array(NxU32 capacity, const Alloc& alloc = Alloc())
  534. : Alloc(alloc)
  535. {
  536. if(mCapacity>0)
  537. allocate(mCapacity);
  538. }
  539. /*!
  540. Copy-constructor. Copy all entries from other array
  541. */
  542. template <class A>
  543. NX_INLINE Array(const Array<T,A>& other, const Alloc& alloc = Alloc())
  544. {
  545. if(other.mSize > 0)
  546. {
  547. mData = allocate(mSize = mCapacity = other.mSize);
  548. copy(mData, other.mData, mSize);
  549. }
  550. }
  551. /*!
  552. Default destructor
  553. */
  554. NX_INLINE ~Array()
  555. {
  556. destroy(0, mSize);
  557. if(mCapacity)
  558. deallocate(mData);
  559. }
  560. /*!
  561. Assignment operator. Copy content (deep-copy)
  562. */
  563. template <class A>
  564. NX_INLINE const Array& operator= (const Array<T,A>& t)
  565. {
  566. if(&t == this)
  567. return *this;
  568. if(mCapacity < t.mSize)
  569. {
  570. destroy(0,mSize);
  571. deallocate(mData);
  572. mData = allocate(t.mCapacity);
  573. mCapacity = t.mCapacity;
  574. copy(mData,t.mData,t.mSize);
  575. }
  576. else
  577. {
  578. NxU32 m = NxMin(t.mSize,mSize);
  579. copy(mData,t.mData,m);
  580. for(NxU32 i = m; i < mSize;i++)
  581. mData[i].~T();
  582. for(NxU32 i = m; i < t.mSize; i++)
  583. new(mData+i)T(t.mData[i]);
  584. }
  585. mSize = t.mSize;
  586. return *this;
  587. }
  588. /*!
  589. Array indexing operator.
  590. \param i
  591. The index of the element that will be returned.
  592. \return
  593. The element i in the array.
  594. */
  595. NX_INLINE const T& operator[] (NxU32 i) const
  596. {
  597. return mData[i];
  598. }
  599. /*!
  600. Array indexing operator.
  601. \param i
  602. The index of the element that will be returned.
  603. \return
  604. The element i in the array.
  605. */
  606. NX_INLINE T& operator[] (NxU32 i)
  607. {
  608. return mData[i];
  609. }
  610. /*!
  611. Returns a pointer to the initial element of the array.
  612. \return
  613. a pointer to the initial element of the array.
  614. */
  615. NX_INLINE ConstIterator begin() const
  616. {
  617. return mData;
  618. }
  619. NX_INLINE Iterator begin()
  620. {
  621. return mData;
  622. }
  623. /*!
  624. Returns an iterator beyond the last element of the array. Do not dereference.
  625. \return
  626. a pointer to the element beyond the last element of the array.
  627. */
  628. NX_INLINE ConstIterator end() const
  629. {
  630. return mData+mSize;
  631. }
  632. NX_INLINE Iterator end()
  633. {
  634. return mData+mSize;
  635. }
  636. /*!
  637. Returns a reference to the first element of the array. Undefined if the array is empty.
  638. \return a reference to the first element of the array
  639. */
  640. NX_INLINE const T& front() const
  641. {
  642. NX_ASSERT(mSize);
  643. return mData[0];
  644. }
  645. NX_INLINE T& front()
  646. {
  647. NX_ASSERT(mSize);
  648. return mData[0];
  649. }
  650. /*!
  651. Returns a reference to the last element of the array. Undefined if the array is empty
  652. \return a reference to the last element of the array
  653. */
  654. NX_INLINE const T& back() const
  655. {
  656. NX_ASSERT(mSize);
  657. return mData[mSize-1];
  658. }
  659. NX_INLINE T& back()
  660. {
  661. NX_ASSERT(mSize);
  662. return mData[mSize-1];
  663. }
  664. /*!
  665. Returns the number of entries in the array. This can, and probably will,
  666. differ from the array capacity.
  667. \return
  668. The number of of entries in the array.
  669. */
  670. NX_INLINE NxU32 size() const
  671. {
  672. return mSize;
  673. }
  674. /*!
  675. Clears the array.
  676. */
  677. NX_INLINE void clear()
  678. {
  679. destroy(0,mSize);
  680. mSize = 0;
  681. }
  682. /*!
  683. Returns whether the array is empty (i.e. whether its size is 0).
  684. \return
  685. true if the array is empty
  686. */
  687. NX_INLINE bool empty() const
  688. {
  689. return mSize==0;
  690. }
  691. /*!
  692. Finds the first occurrence of an element in the array.
  693. \param a
  694. The element that will be removed.
  695. */
  696. NX_INLINE Iterator find(const T&a)
  697. {
  698. NxU32 index;
  699. for(index=0;index<mSize && mData[index]!=a;index++)
  700. ;
  701. return mData+index;
  702. }
  703. NX_INLINE ConstIterator find(const T&a) const
  704. {
  705. NxU32 index;
  706. for(index=0;index<mSize && mData[index]!=a;index++)
  707. ;
  708. return mData+index;
  709. }
  710. /////////////////////////////////////////////////////////////////////////
  711. /*!
  712. Adds one element to the end of the array. Operation is O(1).
  713. \param a
  714. The element that will be added to this array.
  715. */
  716. /////////////////////////////////////////////////////////////////////////
  717. NX_INLINE T& pushBack(const T& a)
  718. {
  719. if(mCapacity<=mSize)
  720. grow(capacityIncrement());
  721. new((void*)(mData + mSize)) T(a);
  722. return mData[mSize++];
  723. }
  724. /////////////////////////////////////////////////////////////////////////
  725. /*!
  726. Returns the element at the end of the array. Only legal if the array is non-empty.
  727. */
  728. /////////////////////////////////////////////////////////////////////////
  729. NX_INLINE T popBack()
  730. {
  731. NX_ASSERT(mSize);
  732. T t = mData[mSize-1];
  733. mData[--mSize].~T();
  734. return t;
  735. }
  736. /////////////////////////////////////////////////////////////////////////
  737. /*!
  738. Construct one element at the end of the array. Operation is O(1).
  739. */
  740. /////////////////////////////////////////////////////////////////////////
  741. NX_INLINE T& insert()
  742. {
  743. if(mCapacity<=mSize)
  744. grow(capacityIncrement());
  745. return *(new (mData+mSize++)T);
  746. }
  747. /////////////////////////////////////////////////////////////////////////
  748. /*!
  749. Subtracts the element on position i from the array and replace it with
  750. the last element.
  751. Operation is O(1)
  752. \param i
  753. The position of the element that will be subtracted from this array.
  754. \return
  755. The element that was removed.
  756. */
  757. /////////////////////////////////////////////////////////////////////////
  758. NX_INLINE void replaceWithLast(NxU32 i)
  759. {
  760. NX_ASSERT(i<mSize);
  761. mData[i] = mData[--mSize];
  762. mData[mSize].~T();
  763. }
  764. NX_INLINE void replaceWithLast(Iterator i)
  765. {
  766. replaceWithLast(static_cast<NxU32>(i-mData));
  767. }
  768. /////////////////////////////////////////////////////////////////////////
  769. /*!
  770. Replaces the first occurrence of the element a with the last element
  771. Operation is O(n)
  772. \param i
  773. The position of the element that will be subtracted from this array.
  774. \return Returns true if the element has been removed.
  775. */
  776. /////////////////////////////////////////////////////////////////////////
  777. NX_INLINE bool findAndReplaceWithLast(const T& a)
  778. {
  779. NxU32 index;
  780. for(index=0;index<mSize && mData[index]!=a;index++)
  781. ;
  782. if(index >= mSize)
  783. return false;
  784. replaceWithLast(index);
  785. return true;
  786. }
  787. /////////////////////////////////////////////////////////////////////////
  788. /*!
  789. Subtracts the element on position i from the array. Shift the entire
  790. array one step.
  791. Operation is O(n)
  792. \param i
  793. The position of the element that will be subtracted from this array.
  794. \return
  795. The element that was removed.
  796. */
  797. /////////////////////////////////////////////////////////////////////////
  798. NX_INLINE void remove(NxU32 i)
  799. {
  800. NX_ASSERT(i<mSize);
  801. while(i+1<mSize)
  802. {
  803. mData[i] = mData[i+1];
  804. i++;
  805. }
  806. mData[--mSize].~T();
  807. }
  808. //////////////////////////////////////////////////////////////////////////
  809. /*!
  810. Resize array
  811. \param compaction
  812. If set to true and the specified size is smaller than the capacity, a new
  813. memory block which fits the size is allocated and the old one gets freed.
  814. */
  815. //////////////////////////////////////////////////////////////////////////
  816. NX_INLINE void resize(const NxU32 size, const bool compaction = false, const T& a = T())
  817. {
  818. if(size > mCapacity)
  819. {
  820. grow(size);
  821. }
  822. else if (compaction && (size != mCapacity))
  823. {
  824. recreate(size, NxMin(mSize, size));
  825. }
  826. for(NxU32 i = mSize; i < size; i++)
  827. ::new(mData+i)T(a);
  828. if (!compaction) // With compaction, these elements have been deleted already
  829. {
  830. for(NxU32 i = size; i < mSize; i++)
  831. mData[i].~T();
  832. }
  833. mSize = size;
  834. }
  835. //////////////////////////////////////////////////////////////////////////
  836. /*!
  837. Resize array such that only as much memory is allocated to hold the
  838. existing elements
  839. */
  840. //////////////////////////////////////////////////////////////////////////
  841. NX_INLINE void shrink()
  842. {
  843. resize(mSize, true);
  844. }
  845. //////////////////////////////////////////////////////////////////////////
  846. /*!
  847. Deletes all array elements and frees memory.
  848. */
  849. //////////////////////////////////////////////////////////////////////////
  850. NX_INLINE void reset()
  851. {
  852. resize(0, true);
  853. }
  854. //////////////////////////////////////////////////////////////////////////
  855. /*!
  856. Ensure that the array has at least size capacity.
  857. */
  858. //////////////////////////////////////////////////////////////////////////
  859. NX_INLINE void reserve(const NxU32 size)
  860. {
  861. if(size > mCapacity)
  862. grow(size);
  863. }
  864. //////////////////////////////////////////////////////////////////////////
  865. /*!
  866. Query the capacity(allocated mem) for the array.
  867. */
  868. //////////////////////////////////////////////////////////////////////////
  869. NX_INLINE NxU32 capacity() const
  870. {
  871. return mCapacity;
  872. }
  873. private:
  874. NX_INLINE T* allocate(size_t capacity)
  875. {
  876. return (T*)Alloc::allocate(sizeof(T) * capacity, __FILE__, __LINE__);
  877. }
  878. NX_INLINE void deallocate(void *mem)
  879. {
  880. Alloc::deallocate(mem);
  881. }
  882. NX_INLINE void copy(T* dst, const T* src, size_t count)
  883. {
  884. for(size_t i=0;i<count;i++)
  885. ::new (dst+i)T(src[i]);
  886. }
  887. NX_INLINE void destroy(size_t start, size_t end)
  888. {
  889. for(size_t i = start; i<end; i++)
  890. mData[i].~T();
  891. }
  892. // The idea here is to prevent accidental brain-damage with pushBack or insert. Unfortunately
  893. // it interacts badly with InlineArrays with smaller inline allocations.
  894. // TODO(dsequeira): policy template arg, this is exactly what they're for.
  895. NX_INLINE NxU32 capacityIncrement() const
  896. {
  897. return mCapacity == 0 ? 1 : mCapacity * 2;
  898. }
  899. /*!
  900. Creates a new memory block, copies all entries to the new block and destroys old entries.
  901. \param capacity
  902. The number of entries that the set should be able to hold.
  903. \param copyCount
  904. The number of entries to copy.
  905. */
  906. NX_INLINE void recreate(NxU32 capacity, NxU32 copyCount)
  907. {
  908. NX_ASSERT(capacity >= copyCount);
  909. NX_ASSERT(mSize >= copyCount);
  910. T* newData = allocate(capacity);
  911. NX_ASSERT( ((newData != NULL) && (capacity > 0)) ||
  912. ((newData == NULL) && (capacity == 0)) );
  913. if(mCapacity)
  914. {
  915. copy(newData,mData,copyCount);
  916. destroy(0,mSize);
  917. deallocate(mData);
  918. }
  919. mData = newData;
  920. mCapacity = capacity;
  921. }
  922. /*!
  923. Resizes the available memory for the array.
  924. \param capacity
  925. The number of entries that the set should be able to hold.
  926. */
  927. NX_INLINE void grow(NxU32 capacity)
  928. {
  929. NX_ASSERT(mCapacity < capacity);
  930. recreate(capacity, mSize);
  931. }
  932. };
  933. // array that pre-allocates for N elements
  934. template <typename T, NxU32 N, typename Alloc = typename Internal::AllocatorTraits<T>::Type>
  935. class InlineArray : public Array<T, InlineAllocator<N * sizeof(T), Alloc> >
  936. {
  937. typedef InlineAllocator<N * sizeof(T), Alloc> Allocator;
  938. public:
  939. NX_INLINE InlineArray(const Alloc& alloc = Alloc())
  940. : Array<T, Allocator>(alloc)
  941. {}
  942. };
  943. }
  944. template <typename T>
  945. NX_INLINE NvStrideIterator<T> getStrideIterator(CONVEX_DECOMPOSITION::Array<T>& array)
  946. {
  947. return NvStrideIterator<T>(array.begin(), sizeof(T));
  948. }
  949. template <typename T>
  950. NX_INLINE NvStrideIterator<const T> getConstStrideIterator(CONVEX_DECOMPOSITION::Array<T>& array)
  951. {
  952. return NvStrideIterator<const T>(array.begin(), sizeof(T));
  953. }
  954. #endif
  955. #ifndef NV_FOUNDATION_BITUTILS_H
  956. #define NV_FOUNDATION_BITUTILS_H
  957. namespace CONVEX_DECOMPOSITION
  958. {
  959. NX_INLINE NxU32 bitCount32(NxU32 v)
  960. {
  961. // from http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
  962. NxU32 const w = v - ((v >> 1) & 0x55555555);
  963. NxU32 const x = (w & 0x33333333) + ((w >> 2) & 0x33333333);
  964. return ((x + (x >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
  965. }
  966. /*!
  967. Return the index of the highest set bit. Or 0 if no bits are set.
  968. */
  969. NX_INLINE NxU32 highestSetBit32(NxU32 v)
  970. {
  971. for(NxU32 j = 32; j-- > 0;)
  972. {
  973. if(v&(1<<j))
  974. return j;
  975. }
  976. return 0;
  977. }
  978. NX_INLINE bool isPowerOfTwo(NxU32 x)
  979. {
  980. return x!=0 && (x & x-1) == 0;
  981. }
  982. // "Next Largest Power of 2
  983. // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
  984. // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
  985. // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
  986. // largest power of 2. For a 32-bit value:"
  987. NX_INLINE NxU32 nextPowerOfTwo(NxU32 x)
  988. {
  989. x |= (x >> 1);
  990. x |= (x >> 2);
  991. x |= (x >> 4);
  992. x |= (x >> 8);
  993. x |= (x >> 16);
  994. return x+1;
  995. }
  996. // Helper function to approximate log2 of an integer value (assumes that the input is actually power of two)
  997. NX_INLINE NxU32 ilog2(NxU32 num)
  998. {
  999. for (NxU32 i=0; i<32; i++)
  1000. {
  1001. num >>= 1;
  1002. if (num == 0) return i;
  1003. }
  1004. NX_ASSERT(0);
  1005. return (NxU32)-1;
  1006. }
  1007. NX_INLINE int intChop(const NxF32& f)
  1008. {
  1009. NxI32 a = *reinterpret_cast<const NxI32*>(&f); // take bit pattern of float into a register
  1010. NxI32 sign = (a>>31); // sign = 0xFFFFFFFF if original value is negative, 0 if positive
  1011. NxI32 mantissa = (a&((1<<23)-1))|(1<<23); // extract mantissa and add the hidden bit
  1012. NxI32 exponent = ((a&0x7fffffff)>>23)-127; // extract the exponent
  1013. NxI32 r = ((NxU32)(mantissa)<<8)>>(31-exponent); // ((1<<exponent)*mantissa)>>24 -- (we know that mantissa > (1<<24))
  1014. return ((r ^ (sign)) - sign ) &~ (exponent>>31); // add original sign. If exponent was negative, make return value 0.
  1015. }
  1016. NX_INLINE int intFloor(const NxF32& f)
  1017. {
  1018. NxI32 a = *reinterpret_cast<const NxI32*>(&f); // take bit pattern of float into a register
  1019. NxI32 sign = (a>>31); // sign = 0xFFFFFFFF if original value is negative, 0 if positive
  1020. a&=0x7fffffff; // we don't need the sign any more
  1021. NxI32 exponent = (a>>23)-127; // extract the exponent
  1022. NxI32 expsign = ~(exponent>>31); // 0xFFFFFFFF if exponent is positive, 0 otherwise
  1023. NxI32 imask = ( (1<<(31-(exponent))))-1; // mask for true integer values
  1024. NxI32 mantissa = (a&((1<<23)-1)); // extract mantissa (without the hidden bit)
  1025. NxI32 r = ((NxU32)(mantissa|(1<<23))<<8)>>(31-exponent); // ((1<<exponent)*(mantissa|hidden bit))>>24 -- (we know that mantissa > (1<<24))
  1026. r = ((r & expsign) ^ (sign)) + ((!((mantissa<<8)&imask)&(expsign^((a-1)>>31)))&sign); // if (fabs(value)<1.0) value = 0; copy sign; if (value < 0 && value==(int)(value)) value++;
  1027. return r;
  1028. }
  1029. NX_INLINE int intCeil(const NxF32& f)
  1030. {
  1031. NxI32 a = *reinterpret_cast<const NxI32*>(&f) ^ 0x80000000; // take bit pattern of float into a register
  1032. NxI32 sign = (a>>31); // sign = 0xFFFFFFFF if original value is negative, 0 if positive
  1033. a&=0x7fffffff; // we don't need the sign any more
  1034. NxI32 exponent = (a>>23)-127; // extract the exponent
  1035. NxI32 expsign = ~(exponent>>31); // 0xFFFFFFFF if exponent is positive, 0 otherwise
  1036. NxI32 imask = ( (1<<(31-(exponent))))-1; // mask for true integer values
  1037. NxI32 mantissa = (a&((1<<23)-1)); // extract mantissa (without the hidden bit)
  1038. NxI32 r = ((NxU32)(mantissa|(1<<23))<<8)>>(31-exponent); // ((1<<exponent)*(mantissa|hidden bit))>>24 -- (we know that mantissa > (1<<24))
  1039. r = ((r & expsign) ^ (sign)) + ((!((mantissa<<8)&imask)&(expsign^((a-1)>>31)))&sign); // if (fabs(value)<1.0) value = 0; copy sign; if (value < 0 && value==(int)(value)) value++;
  1040. return -r;
  1041. }
  1042. }
  1043. #endif
  1044. #ifndef NV_FOUNDATION_HASHFUNCTION_H
  1045. #define NV_FOUNDATION_HASHFUNCTION_H
  1046. /*!
  1047. Central definition of hash functions
  1048. */
  1049. namespace CONVEX_DECOMPOSITION
  1050. {
  1051. // Hash functions
  1052. template<class T>
  1053. NxU32 hash(const T& key)
  1054. {
  1055. return (NxU32)key;
  1056. }
  1057. // Thomas Wang's 32 bit mix
  1058. // http://www.cris.com/~Ttwang/tech/inthash.htm
  1059. template<>
  1060. NX_INLINE NxU32 hash<NxU32>(const NxU32& key)
  1061. {
  1062. NxU32 k = key;
  1063. k += ~(k << 15);
  1064. k ^= (k >> 10);
  1065. k += (k << 3);
  1066. k ^= (k >> 6);
  1067. k += ~(k << 11);
  1068. k ^= (k >> 16);
  1069. return (NxU32)k;
  1070. }
  1071. template<>
  1072. NX_INLINE NxU32 hash<NxI32>(const NxI32& key)
  1073. {
  1074. return hash((NxU32)key);
  1075. }
  1076. // Thomas Wang's 64 bit mix
  1077. // http://www.cris.com/~Ttwang/tech/inthash.htm
  1078. template<>
  1079. NX_INLINE NxU32 hash<NxU64>(const NxU64& key)
  1080. {
  1081. NxU64 k = key;
  1082. k += ~(k << 32);
  1083. k ^= (k >> 22);
  1084. k += ~(k << 13);
  1085. k ^= (k >> 8);
  1086. k += (k << 3);
  1087. k ^= (k >> 15);
  1088. k += ~(k << 27);
  1089. k ^= (k >> 31);
  1090. return (NxU32)k;
  1091. }
  1092. // Helper for pointer hashing
  1093. template<int size>
  1094. NxU32 PointerHash(const void* ptr);
  1095. template<>
  1096. NX_INLINE NxU32 PointerHash<4>(const void* ptr)
  1097. {
  1098. return hash<NxU32>(static_cast<NxU32>(reinterpret_cast<size_t>(ptr)));
  1099. }
  1100. template<>
  1101. NX_INLINE NxU32 PointerHash<8>(const void* ptr)
  1102. {
  1103. return hash<NxU64>(reinterpret_cast<size_t>(ptr));
  1104. }
  1105. // Hash function for pointers
  1106. template<class T>
  1107. NX_INLINE NxU32 hash(T* key)
  1108. {
  1109. return PointerHash<sizeof(const void*)>(key);
  1110. }
  1111. // Hash function object for pointers
  1112. template <class T>
  1113. struct PointerHashFunctor
  1114. {
  1115. NxU32 operator()(const T* t) const
  1116. {
  1117. return PointerHash<sizeof(T*)>(t);
  1118. }
  1119. bool operator()(const T* t0, const T* t1) const
  1120. {
  1121. return t0 == t1;
  1122. }
  1123. };
  1124. /*
  1125. --------------------------------------------------------------------
  1126. lookup2.c, by Bob Jenkins, December 1996, Public Domain.
  1127. --------------------------------------------------------------------
  1128. --------------------------------------------------------------------
  1129. mix -- mix 3 32-bit values reversibly.
  1130. For every delta with one or two bit set, and the deltas of all three
  1131. high bits or all three low bits, whether the original value of a,b,c
  1132. is almost all zero or is uniformly distributed,
  1133. * If mix() is run forward or backward, at least 32 bits in a,b,c
  1134. have at least 1/4 probability of changing.
  1135. * If mix() is run forward, every bit of c will change between 1/3 and
  1136. 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
  1137. mix() was built out of 36 single-cycle latency instructions in a
  1138. structure that could supported 2x parallelism, like so:
  1139. a -= b;
  1140. a -= c; x = (c>>13);
  1141. b -= c; a ^= x;
  1142. b -= a; x = (a<<8);
  1143. c -= a; b ^= x;
  1144. c -= b; x = (b>>13);
  1145. ...
  1146. Unfortunately, superscalar Pentiums and Sparcs can't take advantage
  1147. of that parallelism. They've also turned some of those single-cycle
  1148. latency instructions into multi-cycle latency instructions. Still,
  1149. this is the fastest good hash I could find. There were about 2^^68
  1150. to choose from. I only looked at a billion or so.
  1151. --------------------------------------------------------------------
  1152. */
  1153. NX_INLINE NxU32 hashMix(NxU32 &a, NxU32 &b, NxU32 &c)
  1154. {
  1155. a -= b; a -= c; a ^= (c>>13);
  1156. b -= c; b -= a; b ^= (a<<8);
  1157. c -= a; c -= b; c ^= (b>>13);
  1158. a -= b; a -= c; a ^= (c>>12);
  1159. b -= c; b -= a; b ^= (a<<16);
  1160. c -= a; c -= b; c ^= (b>>5);
  1161. a -= b; a -= c; a ^= (c>>3);
  1162. b -= c; b -= a; b ^= (a<<10);
  1163. c -= a; c -= b; c ^= (b>>15);
  1164. }
  1165. NX_INLINE NxU32 hash(const NxU32 *k, NxU32 length)
  1166. {
  1167. NxU32 a,b,c,len;
  1168. /* Set up the internal state */
  1169. len = length;
  1170. a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
  1171. c = 0; /* the previous hash value */
  1172. /*---------------------------------------- handle most of the key */
  1173. while (len >= 3)
  1174. {
  1175. a += k[0];
  1176. b += k[1];
  1177. c += k[2];
  1178. hashMix(a,b,c);
  1179. k += 3;
  1180. len -= 3;
  1181. }
  1182. /*-------------------------------------- handle the last 2 ub4's */
  1183. c += length;
  1184. switch(len) /* all the case statements fall through */
  1185. {
  1186. /* c is reserved for the length */
  1187. case 2 : b+=k[1];
  1188. case 1 : a+=k[0];
  1189. /* case 0: nothing left to add */
  1190. }
  1191. hashMix(a,b,c);
  1192. /*-------------------------------------------- report the result */
  1193. return c;
  1194. }
  1195. template <class Key>
  1196. class Hash
  1197. {
  1198. public:
  1199. NxU32 operator()(const Key &k) const { return hash<Key>(k); }
  1200. bool operator()(const Key &k0, const Key &k1) const { return k0 == k1; }
  1201. };
  1202. class NvStringHash
  1203. {
  1204. public:
  1205. NxU32 operator()(const char *string) const
  1206. {
  1207. // "DJB" string hash
  1208. NxU32 h = 5381;
  1209. for(const char *ptr = string; *ptr; ptr++)
  1210. h = ((h<<5)+h)^*ptr;
  1211. return h;
  1212. }
  1213. bool operator()(const char* string0, const char* string1) const
  1214. {
  1215. return !strcmp(string0, string1);
  1216. }
  1217. };
  1218. }
  1219. #endif
  1220. #ifndef NV_FOUNDATION_HASHINTERNALS
  1221. #define NV_FOUNDATION_HASHINTERNALS
  1222. #pragma warning(push)
  1223. #pragma warning(disable:4127 4512) // disable the 'conditoinal expression is constant' warning message
  1224. namespace CONVEX_DECOMPOSITION
  1225. {
  1226. namespace Internal
  1227. {
  1228. template <class Entry,
  1229. class Key,
  1230. class HashFn,
  1231. class GetKey,
  1232. class Allocator,
  1233. bool compacting>
  1234. class HashBase
  1235. {
  1236. public:
  1237. typedef Entry EntryType;
  1238. HashBase(NxU32 initialTableSize = 64, float loadFactor = 0.75f):
  1239. mLoadFactor(loadFactor),
  1240. mFreeList((NxU32)EOL),
  1241. mTimestamp(0),
  1242. mSize(0),
  1243. mEntries(Allocator(NV_DEBUG_EXP("hashBaseEntries"))),
  1244. mNext(Allocator(NV_DEBUG_EXP("hashBaseNext"))),
  1245. mHash(Allocator(NV_DEBUG_EXP("hashBaseHash")))
  1246. {
  1247. if(initialTableSize)
  1248. reserveInternal(initialTableSize);
  1249. }
  1250. ~HashBase()
  1251. {
  1252. for(NxU32 i = 0;i<mHash.size();i++)
  1253. {
  1254. for(NxU32 j = mHash[i]; j != EOL; j = mNext[j])
  1255. mEntries[j].~Entry();
  1256. }
  1257. }
  1258. static const int EOL = 0xffffffff;
  1259. NX_INLINE Entry *create(const Key &k, bool &exists)
  1260. {
  1261. NxU32 h=0;
  1262. if(mHash.size())
  1263. {
  1264. h = hash(k);
  1265. NxU32 index = mHash[h];
  1266. while(index!=EOL && !HashFn()(GetKey()(mEntries[index]), k))
  1267. index = mNext[index];
  1268. exists = index!=EOL;
  1269. if(exists)
  1270. return &mEntries[index];
  1271. }
  1272. if(freeListEmpty())
  1273. {
  1274. grow();
  1275. h = hash(k);
  1276. }
  1277. NxU32 entryIndex = freeListGetNext();
  1278. mNext[entryIndex] = mHash[h];
  1279. mHash[h] = entryIndex;
  1280. mSize++;
  1281. mTimestamp++;
  1282. return &mEntries[entryIndex];
  1283. }
  1284. NX_INLINE const Entry *find(const Key &k) const
  1285. {
  1286. if(!mHash.size())
  1287. return NULL;
  1288. NxU32 h = hash(k);
  1289. NxU32 index = mHash[h];
  1290. while(index!=EOL && !HashFn()(GetKey()(mEntries[index]), k))
  1291. index = mNext[index];
  1292. return index != EOL ? &mEntries[index]:0;
  1293. }
  1294. NX_INLINE bool erase(const Key &k)
  1295. {
  1296. if(!mHash.size())
  1297. return false;
  1298. NxU32 h = hash(k);
  1299. NxU32 *ptr = &mHash[h];
  1300. while(*ptr!=EOL && !HashFn()(GetKey()(mEntries[*ptr]), k))
  1301. ptr = &mNext[*ptr];
  1302. if(*ptr == EOL)
  1303. return false;
  1304. NxU32 index = *ptr;
  1305. *ptr = mNext[index];
  1306. mEntries[index].~Entry();
  1307. mSize--;
  1308. mTimestamp++;
  1309. if(compacting && index!=mSize)
  1310. replaceWithLast(index);
  1311. freeListAdd(index);
  1312. return true;
  1313. }
  1314. NX_INLINE NxU32 size() const
  1315. {
  1316. return mSize;
  1317. }
  1318. void clear()
  1319. {
  1320. if(!mHash.size())
  1321. return;
  1322. for(NxU32 i = 0;i<mHash.size();i++)
  1323. mHash[i] = (NxU32)EOL;
  1324. for(NxU32 i = 0;i<mEntries.size()-1;i++)
  1325. mNext[i] = i+1;
  1326. mNext[mEntries.size()-1] = (NxU32)EOL;
  1327. mFreeList = 0;
  1328. mSize = 0;
  1329. }
  1330. void reserve(NxU32 size)
  1331. {
  1332. if(size>mHash.size())
  1333. reserveInternal(size);
  1334. }
  1335. NX_INLINE const Entry *getEntries() const
  1336. {
  1337. return &mEntries[0];
  1338. }
  1339. private:
  1340. // free list management - if we're coalescing, then we use mFreeList to hold
  1341. // the top of the free list and it should always be equal to size(). Otherwise,
  1342. // we build a free list in the next() pointers.
  1343. NX_INLINE void freeListAdd(NxU32 index)
  1344. {
  1345. if(compacting)
  1346. {
  1347. mFreeList--;
  1348. NX_ASSERT(mFreeList == mSize);
  1349. }
  1350. else
  1351. {
  1352. mNext[index] = mFreeList;
  1353. mFreeList = index;
  1354. }
  1355. }
  1356. NX_INLINE void freeListAdd(NxU32 start, NxU32 end)
  1357. {
  1358. if(!compacting)
  1359. {
  1360. for(NxU32 i = start; i<end-1; i++) // add the new entries to the free list
  1361. mNext[i] = i+1;
  1362. mNext[end-1] = (NxU32)EOL;
  1363. }
  1364. mFreeList = start;
  1365. }
  1366. NX_INLINE NxU32 freeListGetNext()
  1367. {
  1368. NX_ASSERT(!freeListEmpty());
  1369. if(compacting)
  1370. {
  1371. NX_ASSERT(mFreeList == mSize);
  1372. return mFreeList++;
  1373. }
  1374. else
  1375. {
  1376. NxU32 entryIndex = mFreeList;
  1377. mFreeList = mNext[mFreeList];
  1378. return entryIndex;
  1379. }
  1380. }
  1381. NX_INLINE bool freeListEmpty()
  1382. {
  1383. if(compacting)
  1384. return mSize == mEntries.size();
  1385. else
  1386. return mFreeList == EOL;
  1387. }
  1388. NX_INLINE void replaceWithLast(NxU32 index)
  1389. {
  1390. new(&mEntries[index])Entry(mEntries[mSize]);
  1391. mEntries[mSize].~Entry();
  1392. mNext[index] = mNext[mSize];
  1393. NxU32 h = hash(GetKey()(mEntries[index]));
  1394. NxU32 *ptr;
  1395. for(ptr = &mHash[h]; *ptr!=mSize; ptr = &mNext[*ptr])
  1396. NX_ASSERT(*ptr!=EOL);
  1397. *ptr = index;
  1398. }
  1399. NX_INLINE NxU32 hash(const Key &k) const
  1400. {
  1401. return HashFn()(k)&(mHash.size()-1);
  1402. }
  1403. void reserveInternal(NxU32 size)
  1404. {
  1405. size = nextPowerOfTwo(size);
  1406. // resize the hash and reset
  1407. mHash.resize(size);
  1408. for(NxU32 i=0;i<mHash.size();i++)
  1409. mHash[i] = (NxU32)EOL;
  1410. NX_ASSERT(!(mHash.size()&(mHash.size()-1)));
  1411. NxU32 oldSize = mEntries.size();
  1412. NxU32 newSize = NxU32(float(mHash.size())*mLoadFactor);
  1413. mEntries.resize(newSize);
  1414. mNext.resize(newSize);
  1415. freeListAdd(oldSize,newSize);
  1416. // rehash all the existing entries
  1417. for(NxU32 i=0;i<oldSize;i++)
  1418. {
  1419. NxU32 h = hash(GetKey()(mEntries[i]));
  1420. mNext[i] = mHash[h];
  1421. mHash[h] = i;
  1422. }
  1423. }
  1424. void grow()
  1425. {
  1426. NX_ASSERT(mFreeList == EOL || compacting && mSize == mEntries.size());
  1427. NxU32 size = mHash.size()==0 ? 16 : mHash.size()*2;
  1428. reserve(size);
  1429. }
  1430. Array<Entry, Allocator> mEntries;
  1431. Array<NxU32, Allocator> mNext;
  1432. Array<NxU32, Allocator> mHash;
  1433. float mLoadFactor;
  1434. NxU32 mFreeList;
  1435. NxU32 mTimestamp;
  1436. NxU32 mSize;
  1437. friend class Iter;
  1438. public:
  1439. class Iter
  1440. {
  1441. public:
  1442. NX_INLINE Iter(HashBase &b): mBase(b), mTimestamp(b.mTimestamp), mBucket(0), mEntry((NxU32)b.EOL)
  1443. {
  1444. if(mBase.mEntries.size()>0)
  1445. {
  1446. mEntry = mBase.mHash[0];
  1447. skip();
  1448. }
  1449. }
  1450. NX_INLINE void check() { NX_ASSERT(mTimestamp == mBase.mTimestamp); }
  1451. NX_INLINE Entry operator*() { check(); return mBase.mEntries[mEntry]; }
  1452. NX_INLINE Entry *operator->() { check(); return &mBase.mEntries[mEntry]; }
  1453. NX_INLINE Iter operator++() { check(); advance(); return *this; }
  1454. NX_INLINE Iter operator++(int) { check(); Iter i = *this; advance(); return i; }
  1455. NX_INLINE bool done() { check(); return mEntry == mBase.EOL; }
  1456. private:
  1457. NX_INLINE void advance() { mEntry = mBase.mNext[mEntry]; skip(); }
  1458. NX_INLINE void skip()
  1459. {
  1460. while(mEntry==mBase.EOL)
  1461. {
  1462. if(++mBucket == mBase.mHash.size())
  1463. break;
  1464. mEntry = mBase.mHash[mBucket];
  1465. }
  1466. }
  1467. NxU32 mBucket;
  1468. NxU32 mEntry;
  1469. NxU32 mTimestamp;
  1470. HashBase &mBase;
  1471. };
  1472. };
  1473. template <class Key,
  1474. class HashFn,
  1475. class Allocator = Allocator,
  1476. bool Coalesced = false>
  1477. class HashSetBase
  1478. {
  1479. public:
  1480. struct GetKey { NX_INLINE const Key &operator()(const Key &e) { return e; } };
  1481. typedef HashBase<Key, Key, HashFn, GetKey, Allocator, Coalesced> BaseMap;
  1482. typedef typename BaseMap::Iter Iterator;
  1483. HashSetBase(NxU32 initialTableSize = 64,
  1484. float loadFactor = 0.75f): mBase(initialTableSize,loadFactor) {}
  1485. bool insert(const Key &k)
  1486. {
  1487. bool exists;
  1488. Key *e = mBase.create(k,exists);
  1489. if(!exists)
  1490. new(e)Key(k);
  1491. return !exists;
  1492. }
  1493. NX_INLINE bool contains(const Key &k) const { return mBase.find(k)!=0; }
  1494. NX_INLINE bool erase(const Key &k) { return mBase.erase(k); }
  1495. NX_INLINE NxU32 size() const { return mBase.size(); }
  1496. NX_INLINE void reserve(NxU32 size) { mBase.reserve(size); }
  1497. NX_INLINE void clear() { mBase.clear(); }
  1498. protected:
  1499. BaseMap mBase;
  1500. };
  1501. template <class Key,
  1502. class Value,
  1503. class HashFn,
  1504. class Allocator = Allocator >
  1505. class HashMapBase
  1506. {
  1507. public:
  1508. typedef Pair<const Key,Value> Entry;
  1509. struct GetKey { NX_INLINE const Key &operator()(const Entry &e) { return e.first; } };
  1510. typedef HashBase<Pair<const Key,Value>, Key, HashFn, GetKey, Allocator, true> BaseMap;
  1511. typedef typename BaseMap::Iter Iterator;
  1512. HashMapBase(NxU32 initialTableSize = 64, float loadFactor = 0.75f): mBase(initialTableSize,loadFactor) {}
  1513. bool insert(const Key &k, const Value &v)
  1514. {
  1515. bool exists;
  1516. Entry *e = mBase.create(k,exists);
  1517. if(!exists)
  1518. new(e)Entry(k,v);
  1519. return !exists;
  1520. }
  1521. Value &operator [](const Key &k)
  1522. {
  1523. bool exists;
  1524. Entry *e = mBase.create(k, exists);
  1525. if(!exists)
  1526. new(e)Entry(k,Value());
  1527. return e->second;
  1528. }
  1529. NX_INLINE const Entry * find(const Key &k) const { return mBase.find(k); }
  1530. NX_INLINE bool erase(const Key &k) { return mBase.erase(k); }
  1531. NX_INLINE NxU32 size() const { return mBase.size(); }
  1532. NX_INLINE Iterator getIterator() { return Iterator(mBase); }
  1533. NX_INLINE void reserve(NxU32 size) { mBase.reserve(size); }
  1534. NX_INLINE void clear() { mBase.clear(); }
  1535. protected:
  1536. BaseMap mBase;
  1537. };
  1538. }
  1539. }
  1540. #pragma warning(pop)
  1541. #endif
  1542. #ifndef NV_FOUNDATION_HASHMAP
  1543. #define NV_FOUNDATION_HASHMAP
  1544. // TODO: make this doxy-format
  1545. //
  1546. // This header defines two hash maps. Hash maps
  1547. // * support custom initial table sizes (rounded up internally to power-of-2)
  1548. // * support custom static allocator objects
  1549. // * auto-resize, based on a load factor (i.e. a 64-entry .75 load factor hash will resize
  1550. // when the 49th element is inserted)
  1551. // * are based on open hashing
  1552. // * have O(1) contains, erase
  1553. //
  1554. // Maps have STL-like copying semantics, and properly initialize and destruct copies of objects
  1555. //
  1556. // There are two forms of map: coalesced and uncoalesced. Coalesced maps keep the entries in the
  1557. // initial segment of an array, so are fast to iterate over; however deletion is approximately
  1558. // twice as expensive.
  1559. //
  1560. // HashMap<T>:
  1561. // bool insert(const Key &k, const Value &v) O(1) amortized (exponential resize policy)
  1562. // Value & operator[](const Key &k) O(1) for existing objects, else O(1) amortized
  1563. // const Entry * find(const Key &k); O(1)
  1564. // bool erase(const T &k); O(1)
  1565. // NxU32 size(); constant
  1566. // void reserve(NxU32 size); O(MAX(currentOccupancy,size))
  1567. // void clear(); O(currentOccupancy) (with zero constant for objects without destructors)
  1568. // Iterator getIterator();
  1569. //
  1570. // operator[] creates an entry if one does not exist, initializing with the default constructor.
  1571. // CoalescedHashMap<T> does not support getInterator, but instead supports
  1572. // const Key *getEntries();
  1573. //
  1574. // Use of iterators:
  1575. //
  1576. // for(HashMap::Iterator iter = test.getIterator(); !iter.done(); ++iter)
  1577. // myFunction(iter->first, iter->second);
  1578. namespace CONVEX_DECOMPOSITION
  1579. {
  1580. template <class Key,
  1581. class Value,
  1582. class HashFn = Hash<Key>,
  1583. class Allocator = Allocator >
  1584. class HashMap: public Internal::HashMapBase<Key, Value, HashFn, Allocator>
  1585. {
  1586. public:
  1587. typedef Internal::HashMapBase<Key, Value, HashFn, Allocator> HashMapBase;
  1588. typedef typename HashMapBase::Iterator Iterator;
  1589. HashMap(NxU32 initialTableSize = 64, float loadFactor = 0.75f): HashMapBase(initialTableSize,loadFactor) {}
  1590. Iterator getIterator() { return Iterator(HashMapBase::mBase); }
  1591. };
  1592. template <class Key,
  1593. class Value,
  1594. class HashFn = Hash<Key>,
  1595. class Allocator = Allocator >
  1596. class CoalescedHashMap: public Internal::HashMapBase<Key, Value, HashFn, Allocator>
  1597. {
  1598. typedef Internal::HashMapBase<Key, Value, HashFn, Allocator> HashMapBase;
  1599. CoalescedHashMap(NxU32 initialTableSize = 64, float loadFactor = 0.75f): HashMapBase(initialTableSize,loadFactor){}
  1600. const Key *getEntries() const { return HashMapBase::mBase.getEntries(); }
  1601. };
  1602. }
  1603. #endif
  1604. #endif