AkSet.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*******************************************************************************
  2. The content of this file includes portions of the AUDIOKINETIC Wwise Technology
  3. released in source code form as part of the SDK installer package.
  4. Commercial License Usage
  5. Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
  6. may use this file in accordance with the end user license agreement provided
  7. with the software or, alternatively, in accordance with the terms contained in a
  8. written agreement between you and Audiokinetic Inc.
  9. Apache License Usage
  10. Alternatively, this file may be used under the Apache License, Version 2.0 (the
  11. "Apache License"); you may not use this file except in compliance with the
  12. Apache License. You may obtain a copy of the Apache License at
  13. http://www.apache.org/licenses/LICENSE-2.0.
  14. Unless required by applicable law or agreed to in writing, software distributed
  15. under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
  16. OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
  17. the specific language governing permissions and limitations under the License.
  18. Copyright (c) 2023 Audiokinetic Inc.
  19. *******************************************************************************/
  20. //////////////////////////////////////////////////////////////////////
  21. //
  22. // AkSet.h
  23. //
  24. //////////////////////////////////////////////////////////////////////
  25. #ifndef _AKSET_H_
  26. #define _AKSET_H_
  27. #include <AK/Tools/Common/AkKeyArray.h>
  28. // AkSetType
  29. // - An optional set type specifier which is passed into some set operations. If it is not included, SetType_Inclusion is assumed.
  30. //
  31. enum AkSetType
  32. {
  33. SetType_Inclusion, // <- An AkSet object with type SetType_Inclusion is a set where each element in the array
  34. // represents an element in the set. An empty array represents the empty set.
  35. SetType_Exclusion // <- An AkSet object with type SetType_Exclusion is an 'inverted' set, where each element in the array
  36. // represents and element NOT in the set. An empty array represents the universal set.
  37. };
  38. template<typename T>
  39. struct AkSetGetKey{ static AkForceInline T& Get(T& in_item){ return in_item; } };
  40. // AkSet
  41. //
  42. // Set container type, implemented as a sorted array of unique items
  43. //
  44. template< typename T, class U_POOL = ArrayPoolDefault, class uGrowBy = AkGrowByPolicy_DEFAULT, class TMovePolicy = AkAssignmentMovePolicy<T>, class TComparePolicy = AkDefaultSortedKeyCompare<T> >
  45. class AkSet : public AkSortedKeyArray < T, T, U_POOL, AkSetGetKey<T>, uGrowBy, TMovePolicy, TComparePolicy >
  46. {
  47. public:
  48. bool Contains(T in_item) const { return AkSortedKeyArray < T, T, U_POOL, AkSetGetKey<T>, uGrowBy, TMovePolicy, TComparePolicy >::Exists(in_item) != NULL; }
  49. };
  50. // AkDisjoint
  51. // - Returns true if the intersection of A and B is the empty set.
  52. //
  53. template< typename T, class U_POOL = ArrayPoolDefault, class uGrowBy, class TMovePolicy, class TComparePolicy >
  54. static bool AkDisjoint(const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  55. {
  56. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itA = in_A.Begin();
  57. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itB = in_B.Begin();
  58. while (itA != in_A.End() && itB != in_B.End())
  59. {
  60. if (*itA == *itB)
  61. return false;
  62. else if (*itA < *itB)
  63. ++itA;
  64. else
  65. ++itB;
  66. }
  67. return true;
  68. }
  69. // AkIntersect
  70. // - Return true if the intersection of A and B is not the empty set.
  71. //
  72. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  73. static bool AkIntersect(const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  74. {
  75. return !AkDisjoint(in_A, in_B);
  76. }
  77. // AkIsSubset
  78. // - Return true if in_A is a subset of in_B
  79. //
  80. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  81. static bool AkIsSubset(const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  82. {
  83. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itA = in_A.Begin();
  84. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itB = in_B.Begin();
  85. while (itA != in_A.End() && itB != in_B.End())
  86. {
  87. if (TComparePolicy::Equal(&in_A, *itA, *itB))
  88. {
  89. ++itA; ++itB;
  90. }
  91. else if (TComparePolicy::Lesser(&in_A, *itA, *itB))
  92. {
  93. return false;//an element of A is not in B
  94. }
  95. else
  96. ++itB;
  97. }
  98. return (itA == in_A.End());
  99. }
  100. // AkCountIntersection
  101. // - Helper function to count the number of elements that are in both in_A and in_B.
  102. //
  103. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  104. static AkUInt32 AkCountIntersection(const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  105. {
  106. AkUInt32 uSize = 0;
  107. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itA = in_A.Begin();
  108. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itB = in_B.Begin();
  109. while (itA != in_A.End() && itB != in_B.End())
  110. {
  111. if (TComparePolicy::Equal(&in_A, *itA, *itB))
  112. {
  113. ++uSize; ++itA; ++itB;
  114. }
  115. else if (TComparePolicy::Lesser(&in_A, *itA, *itB))
  116. {
  117. ++itA;
  118. }
  119. else
  120. {
  121. ++itB;
  122. }
  123. }
  124. return uSize;
  125. }
  126. // AkSubtraction
  127. // - In-place set subtraction ( A = A - B )
  128. //
  129. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy>
  130. static bool AkSubtraction(AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  131. {
  132. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itAr, itAw;
  133. itAr = itAw = in_A.Begin();
  134. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itB = in_B.Begin();
  135. while (itAr != in_A.End())
  136. {
  137. if (itB == in_B.End() || TComparePolicy::Lesser(&in_A, *itAr, *itB))
  138. {
  139. if (itAw != itAr)
  140. *itAw = *itAr;
  141. ++itAw;
  142. ++itAr;
  143. }
  144. else if (TComparePolicy::Equal(&in_A, *itAr, *itB))
  145. {
  146. ++itB;
  147. ++itAr;
  148. }
  149. else
  150. {
  151. ++itB;
  152. }
  153. }
  154. in_A.Resize((AkUInt32)(itAw.pItem - in_A.Begin().pItem));
  155. return true;
  156. }
  157. // AkIntersection
  158. // - In-place set intersection ( A = A n B )
  159. //
  160. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  161. static bool AkIntersection(AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  162. {
  163. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itAr, itAw;
  164. itAr = itAw = in_A.Begin();
  165. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itB = in_B.Begin();
  166. while (itAr != in_A.End() && itB != in_B.End())
  167. {
  168. if (TComparePolicy::Equal(&in_A, *itAr, *itB))
  169. {
  170. if (itAw != itAr)
  171. *itAw = *itAr;
  172. ++itAw;
  173. ++itAr;
  174. ++itB;
  175. }
  176. else if (TComparePolicy::Lesser(&in_A, *itAr,*itB))
  177. {
  178. ++itAr;
  179. }
  180. else
  181. {
  182. ++itB;
  183. }
  184. }
  185. in_A.Resize((AkUInt32)(itAw.pItem - in_A.Begin().pItem));
  186. return true;
  187. }
  188. // AkIntersection
  189. // - Out-of-place set intersection ( res = A n B )
  190. //
  191. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  192. static bool AkIntersection(AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& out_res, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  193. {
  194. out_res.RemoveAll();
  195. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itA = in_A.Begin();
  196. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itB = in_B.Begin();
  197. while (itA != in_A.End() && itB != in_B.End())
  198. {
  199. if (TComparePolicy::Equal(&in_A, *itA, *itB))
  200. {
  201. out_res.AddLast(*itA);
  202. ++itA;
  203. ++itB;
  204. }
  205. else if (TComparePolicy::Lesser(&in_A, *itA,*itB))
  206. {
  207. ++itA;
  208. }
  209. else
  210. {
  211. ++itB;
  212. }
  213. }
  214. return true;
  215. }
  216. // AkUnion
  217. // - Set union ( A = A U B ).
  218. // NOTE: Preforms a memory allocation and may fail.
  219. //
  220. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  221. static bool AkUnion(AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& io_A, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B)
  222. {
  223. AkInt32 uSizeNeeded = io_A.Length() + in_B.Length() - AkCountIntersection(io_A, in_B);
  224. AkSet<T, U_POOL, uGrowBy> result;
  225. if (result.Resize(uSizeNeeded))
  226. {
  227. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itRes = result.Begin();
  228. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itA = io_A.Begin();
  229. typename AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>::Iterator itB = in_B.Begin();
  230. while (itB != in_B.End() || itA != io_A.End())
  231. {
  232. if ( itB != in_B.End() && (itA == io_A.End() || TComparePolicy::Lesser(&io_A, *itB, *itA)))
  233. {
  234. *itRes = *itB;
  235. ++itB;
  236. }
  237. else if (itB == in_B.End() || TComparePolicy::Lesser(&io_A, *itA,*itB) )
  238. {
  239. *itRes = *itA;
  240. ++itA;
  241. }
  242. else //if ( *itA == *itC)
  243. {
  244. *itRes = *itA;
  245. ++itA;
  246. ++itB;
  247. }
  248. ++itRes;
  249. }
  250. io_A.Transfer(result);
  251. return true;
  252. }
  253. return false;
  254. }
  255. typedef AkSet< AkUniqueID, ArrayPoolDefault > AkUniqueIDSet;
  256. // AkIntersect
  257. // - Return true if the intersection of in_A (a set of type in_typeA), and in_B (a set of type in_typeB) is not the empty set.
  258. //
  259. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  260. static inline bool AkIntersect(const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, AkSetType in_typeA, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B, AkSetType in_typeB)
  261. {
  262. if (in_typeA == SetType_Inclusion)
  263. {
  264. if (in_typeB == SetType_Inclusion)
  265. return !AkDisjoint(in_A, in_B);
  266. else//(in_typeB == SetType_Exclusion)
  267. return !AkIsSubset(in_A, in_B);
  268. }
  269. else//(in_typeA == SetType_Exclusion)
  270. {
  271. if (in_typeB == SetType_Inclusion)
  272. return !AkIsSubset(in_B, in_A);
  273. else//(in_typeB == SetType_Exclusion)
  274. return true;//Assuming an infinite space of possible elements.
  275. }
  276. }
  277. // AkContains
  278. // - Return true if the element in_item is contained in in_Set, a set of type in_type.
  279. //
  280. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  281. static inline bool AkContains(const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_Set, AkSetType in_type, T in_item)
  282. {
  283. return (in_type == SetType_Inclusion && in_Set.Contains(in_item)) ||
  284. (in_type == SetType_Exclusion && !in_Set.Contains(in_item));
  285. }
  286. // AkSubtraction
  287. // - pseudo in-place set subtraction (A = A - B) with set type specifiers.
  288. // NOTE: Memory may be allocated (in AkUnion) so prepare for failure.
  289. //
  290. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  291. static inline bool AkSubtraction(AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_A, AkSetType in_typeA, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B, AkSetType in_typeB)
  292. {
  293. if (in_typeA == SetType_Inclusion)
  294. {
  295. if (in_typeB == SetType_Inclusion)
  296. return AkSubtraction(in_A, in_B);
  297. else//(in_typeB == SetType_Exclusion)
  298. return AkIntersection(in_A, in_B);
  299. }
  300. else//(in_typeA == SetType_Exclusion)
  301. {
  302. if (in_typeB == SetType_Inclusion)
  303. return AkUnion(in_A, in_B);
  304. else//(in_typeB == SetType_Exclusion)
  305. return AkIntersection(in_A, in_B);
  306. }
  307. }
  308. // AkUnion
  309. // - Pseudo in-place set union (A = A + B)
  310. // NOTE: Memory may be allocated (in AkUnion) so prepare for failure.
  311. //
  312. template< typename T, class U_POOL, class uGrowBy, class TMovePolicy, class TComparePolicy >
  313. static inline bool AkUnion(AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& io_A, AkSetType& io_typeA, const AkSet<T, U_POOL, uGrowBy, TMovePolicy, TComparePolicy>& in_B, AkSetType in_typeB)
  314. {
  315. if (io_typeA == SetType_Inclusion)
  316. {
  317. if (in_typeB == SetType_Inclusion)
  318. return AkUnion(io_A, in_B);
  319. else//(in_typeB == SetType_Exclusion)
  320. {
  321. AkSet<T, U_POOL, uGrowBy> temp;
  322. temp.Transfer(io_A);
  323. if (io_A.Copy(in_B) == AK_Success)
  324. {
  325. io_typeA = SetType_Exclusion;
  326. AkSubtraction(io_A, temp);
  327. temp.Term();
  328. return true;
  329. }
  330. else
  331. {
  332. io_A.Transfer(temp);
  333. return false;
  334. }
  335. }
  336. }
  337. else//(in_typeA == SetType_Exclusion)
  338. {
  339. if (in_typeB == SetType_Inclusion)
  340. return AkSubtraction(io_A, in_B);
  341. else//(in_typeB == SetType_Exclusion)
  342. return AkIntersection(io_A, in_B);
  343. }
  344. }
  345. #endif