BitArray.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace UnityEngine.Rendering
  5. {
  6. /// <summary>
  7. /// IBitArray interface.
  8. /// </summary>
  9. public interface IBitArray
  10. {
  11. /// <summary>Number of elements in the bit array.</summary>
  12. uint capacity { get; }
  13. /// <summary>True if all bits are 0.</summary>
  14. bool allFalse { get; }
  15. /// <summary>True if all bits are 1.</summary>
  16. bool allTrue { get; }
  17. /// <summary>
  18. /// Returns the state of the bit at a specific index.
  19. /// </summary>
  20. /// <param name="index">Index of the bit.</param>
  21. /// <returns>State of the bit at the provided index.</returns>
  22. bool this[uint index] { get; set; }
  23. /// <summary>Returns the bit array in a human readable form.</summary>
  24. string humanizedData { get; }
  25. /// <summary>
  26. /// Bit-wise And operation.
  27. /// </summary>
  28. /// <param name="other">Bit array with which to the And operation.</param>
  29. /// <returns>The resulting bit array.</returns>
  30. IBitArray BitAnd(IBitArray other);
  31. /// <summary>
  32. /// Bit-wise Or operation.
  33. /// </summary>
  34. /// <param name="other">Bit array with which to the Or operation.</param>
  35. /// <returns>The resulting bit array.</returns>
  36. IBitArray BitOr(IBitArray other);
  37. /// <summary>
  38. /// Invert the bit array.
  39. /// </summary>
  40. /// <returns></returns>
  41. IBitArray BitNot();
  42. }
  43. // /!\ Important for serialization:
  44. // Serialization helper will rely on the name of the struct type.
  45. // In order to work, it must be BitArrayN where N is the capacity without suffix.
  46. /// <summary>
  47. /// Bit array of size 8.
  48. /// </summary>
  49. [Serializable]
  50. [System.Diagnostics.DebuggerDisplay("{this.GetType().Name} {humanizedData}")]
  51. public struct BitArray8 : IBitArray
  52. {
  53. [SerializeField]
  54. byte data;
  55. /// <summary>Number of elements in the bit array.</summary>
  56. public uint capacity => 8u;
  57. /// <summary>True if all bits are 0.</summary>
  58. public bool allFalse => data == 0u;
  59. /// <summary>True if all bits are 1.</summary>
  60. public bool allTrue => data == byte.MaxValue;
  61. /// <summary>Returns the bit array in a human readable form.</summary>
  62. public string humanizedData => String.Format("{0, " + capacity + "}", Convert.ToString(data, 2)).Replace(' ', '0');
  63. /// <summary>
  64. /// Returns the state of the bit at a specific index.
  65. /// </summary>
  66. /// <param name="index">Index of the bit.</param>
  67. /// <returns>State of the bit at the provided index.</returns>
  68. public bool this[uint index]
  69. {
  70. get => BitArrayUtilities.Get8(index, data);
  71. set => BitArrayUtilities.Set8(index, ref data, value);
  72. }
  73. /// <summary>
  74. /// Constructor.
  75. /// </summary>
  76. /// <param name="initValue">Initialization value.</param>
  77. public BitArray8(byte initValue) => data = initValue;
  78. /// <summary>
  79. /// Constructor.
  80. /// </summary>
  81. /// <param name="bitIndexTrue">List of indices where bits should be set to true.</param>
  82. public BitArray8(IEnumerable<uint> bitIndexTrue)
  83. {
  84. data = (byte)0u;
  85. if (bitIndexTrue == null)
  86. return;
  87. for (int index = bitIndexTrue.Count() - 1; index >= 0; --index)
  88. {
  89. uint bitIndex = bitIndexTrue.ElementAt(index);
  90. if (bitIndex >= capacity) continue;
  91. data |= (byte)(1u << (int)bitIndex);
  92. }
  93. }
  94. /// <summary>
  95. /// Bit-wise Not operator
  96. /// </summary>
  97. /// <param name="a">Bit array with which to do the operation.</param>
  98. /// <returns>The resulting bit array.</returns>
  99. public static BitArray8 operator ~(BitArray8 a) => new BitArray8((byte)~a.data);
  100. /// <summary>
  101. /// Bit-wise Or operator
  102. /// </summary>
  103. /// <param name="a">First bit array.</param>
  104. /// <param name="b">Second bit array.</param>
  105. /// <returns>The resulting bit array.</returns>
  106. public static BitArray8 operator |(BitArray8 a, BitArray8 b) => new BitArray8((byte)(a.data | b.data));
  107. /// <summary>
  108. /// Bit-wise And operator
  109. /// </summary>
  110. /// <param name="a">First bit array.</param>
  111. /// <param name="b">Second bit array.</param>
  112. /// <returns>The resulting bit array.</returns>
  113. public static BitArray8 operator &(BitArray8 a, BitArray8 b) => new BitArray8((byte)(a.data & b.data));
  114. /// <summary>
  115. /// Bit-wise And
  116. /// </summary>
  117. /// <param name="other">Bit array with which to do the operation.</param>
  118. /// <returns>The resulting bit array.</returns>
  119. public IBitArray BitAnd(IBitArray other) => this & (BitArray8)other;
  120. /// <summary>
  121. /// Bit-wise Or
  122. /// </summary>
  123. /// <param name="other">Bit array with which to do the operation.</param>
  124. /// <returns>The resulting bit array.</returns>
  125. public IBitArray BitOr(IBitArray other) => this | (BitArray8)other;
  126. /// <summary>
  127. /// Bit-wise Not
  128. /// </summary>
  129. /// <returns>The resulting bit array.</returns>
  130. public IBitArray BitNot() => ~this;
  131. /// <summary>
  132. /// Equality operator.
  133. /// </summary>
  134. /// <param name="a">First bit array.</param>
  135. /// <param name="b">Second bit array.</param>
  136. /// <returns>True if both bit arrays are equals.</returns>
  137. public static bool operator ==(BitArray8 a, BitArray8 b) => a.data == b.data;
  138. /// <summary>
  139. /// Inequality operator.
  140. /// </summary>
  141. /// <param name="a">First bit array.</param>
  142. /// <param name="b">Second bit array.</param>
  143. /// <returns>True if the bit arrays are not equals.</returns>
  144. public static bool operator !=(BitArray8 a, BitArray8 b) => a.data != b.data;
  145. /// <summary>
  146. /// Equality operator.
  147. /// </summary>
  148. /// <param name="obj">Bit array to compare to.</param>
  149. /// <returns>True if the provided bit array is equal to this..</returns>
  150. public override bool Equals(object obj) => obj is BitArray8 && ((BitArray8)obj).data == data;
  151. /// <summary>
  152. /// Get the hashcode of the bit array.
  153. /// </summary>
  154. /// <returns>Hashcode of the bit array.</returns>
  155. public override int GetHashCode() => 1768953197 + data.GetHashCode();
  156. }
  157. /// <summary>
  158. /// Bit array of size 16.
  159. /// </summary>
  160. [Serializable]
  161. [System.Diagnostics.DebuggerDisplay("{this.GetType().Name} {humanizedData}")]
  162. public struct BitArray16 : IBitArray
  163. {
  164. [SerializeField]
  165. ushort data;
  166. /// <summary>Number of elements in the bit array.</summary>
  167. public uint capacity => 16u;
  168. /// <summary>True if all bits are 0.</summary>
  169. public bool allFalse => data == 0u;
  170. /// <summary>True if all bits are 1.</summary>
  171. public bool allTrue => data == ushort.MaxValue;
  172. /// <summary>Returns the bit array in a human readable form.</summary>
  173. public string humanizedData => System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + capacity + "}", Convert.ToString(data, 2)).Replace(' ', '0'), ".{8}", "$0.").TrimEnd('.');
  174. /// <summary>
  175. /// Returns the state of the bit at a specific index.
  176. /// </summary>
  177. /// <param name="index">Index of the bit.</param>
  178. /// <returns>State of the bit at the provided index.</returns>
  179. public bool this[uint index]
  180. {
  181. get => BitArrayUtilities.Get16(index, data);
  182. set => BitArrayUtilities.Set16(index, ref data, value);
  183. }
  184. /// <summary>
  185. /// Constructor.
  186. /// </summary>
  187. /// <param name="initValue">Initialization value.</param>
  188. public BitArray16(ushort initValue) => data = initValue;
  189. /// <summary>
  190. /// Constructor.
  191. /// </summary>
  192. /// <param name="bitIndexTrue">List of indices where bits should be set to true.</param>
  193. public BitArray16(IEnumerable<uint> bitIndexTrue)
  194. {
  195. data = (ushort)0u;
  196. if (bitIndexTrue == null)
  197. return;
  198. for (int index = bitIndexTrue.Count() - 1; index >= 0; --index)
  199. {
  200. uint bitIndex = bitIndexTrue.ElementAt(index);
  201. if (bitIndex >= capacity) continue;
  202. data |= (ushort)(1u << (int)bitIndex);
  203. }
  204. }
  205. /// <summary>
  206. /// Bit-wise Not operator
  207. /// </summary>
  208. /// <param name="a">Bit array with which to do the operation.</param>
  209. /// <returns>The resulting bit array.</returns>
  210. public static BitArray16 operator ~(BitArray16 a) => new BitArray16((ushort)~a.data);
  211. /// <summary>
  212. /// Bit-wise Or operator
  213. /// </summary>
  214. /// <param name="a">First bit array.</param>
  215. /// <param name="b">Second bit array.</param>
  216. /// <returns>The resulting bit array.</returns>
  217. public static BitArray16 operator |(BitArray16 a, BitArray16 b) => new BitArray16((ushort)(a.data | b.data));
  218. /// <summary>
  219. /// Bit-wise And operator
  220. /// </summary>
  221. /// <param name="a">First bit array.</param>
  222. /// <param name="b">Second bit array.</param>
  223. /// <returns>The resulting bit array.</returns>
  224. public static BitArray16 operator &(BitArray16 a, BitArray16 b) => new BitArray16((ushort)(a.data & b.data));
  225. /// <summary>
  226. /// Bit-wise And
  227. /// </summary>
  228. /// <param name="other">Bit array with which to do the operation.</param>
  229. /// <returns>The resulting bit array.</returns>
  230. public IBitArray BitAnd(IBitArray other) => this & (BitArray16)other;
  231. /// <summary>
  232. /// Bit-wise Or
  233. /// </summary>
  234. /// <param name="other">Bit array with which to do the operation.</param>
  235. /// <returns>The resulting bit array.</returns>
  236. public IBitArray BitOr(IBitArray other) => this | (BitArray16)other;
  237. /// <summary>
  238. /// Bit-wise Not
  239. /// </summary>
  240. /// <returns>The resulting bit array.</returns>
  241. public IBitArray BitNot() => ~this;
  242. /// <summary>
  243. /// Equality operator.
  244. /// </summary>
  245. /// <param name="a">First bit array.</param>
  246. /// <param name="b">Second bit array.</param>
  247. /// <returns>True if both bit arrays are equals.</returns>
  248. public static bool operator ==(BitArray16 a, BitArray16 b) => a.data == b.data;
  249. /// <summary>
  250. /// Inequality operator.
  251. /// </summary>
  252. /// <param name="a">First bit array.</param>
  253. /// <param name="b">Second bit array.</param>
  254. /// <returns>True if the bit arrays are not equals.</returns>
  255. public static bool operator !=(BitArray16 a, BitArray16 b) => a.data != b.data;
  256. /// <summary>
  257. /// Equality operator.
  258. /// </summary>
  259. /// <param name="obj">Bit array to compare to.</param>
  260. /// <returns>True if the provided bit array is equal to this..</returns>
  261. public override bool Equals(object obj) => obj is BitArray16 && ((BitArray16)obj).data == data;
  262. /// <summary>
  263. /// Get the hashcode of the bit array.
  264. /// </summary>
  265. /// <returns>Hashcode of the bit array.</returns>
  266. public override int GetHashCode() => 1768953197 + data.GetHashCode();
  267. }
  268. /// <summary>
  269. /// Bit array of size 32.
  270. /// </summary>
  271. [Serializable]
  272. [System.Diagnostics.DebuggerDisplay("{this.GetType().Name} {humanizedData}")]
  273. public struct BitArray32 : IBitArray
  274. {
  275. [SerializeField]
  276. uint data;
  277. /// <summary>Number of elements in the bit array.</summary>
  278. public uint capacity => 32u;
  279. /// <summary>True if all bits are 0.</summary>
  280. public bool allFalse => data == 0u;
  281. /// <summary>True if all bits are 1.</summary>
  282. public bool allTrue => data == uint.MaxValue;
  283. string humanizedVersion => Convert.ToString(data, 2);
  284. /// <summary>Returns the bit array in a human readable form.</summary>
  285. public string humanizedData => System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + capacity + "}", Convert.ToString(data, 2)).Replace(' ', '0'), ".{8}", "$0.").TrimEnd('.');
  286. /// <summary>
  287. /// Returns the state of the bit at a specific index.
  288. /// </summary>
  289. /// <param name="index">Index of the bit.</param>
  290. /// <returns>State of the bit at the provided index.</returns>
  291. public bool this[uint index]
  292. {
  293. get => BitArrayUtilities.Get32(index, data);
  294. set => BitArrayUtilities.Set32(index, ref data, value);
  295. }
  296. /// <summary>
  297. /// Constructor.
  298. /// </summary>
  299. /// <param name="initValue">Initialization value.</param>
  300. public BitArray32(uint initValue) => data = initValue;
  301. /// <summary>
  302. /// Constructor.
  303. /// </summary>
  304. /// <param name="bitIndexTrue">List of indices where bits should be set to true.</param>
  305. public BitArray32(IEnumerable<uint> bitIndexTrue)
  306. {
  307. data = 0u;
  308. if (bitIndexTrue == null)
  309. return;
  310. for (int index = bitIndexTrue.Count() - 1; index >= 0; --index)
  311. {
  312. uint bitIndex = bitIndexTrue.ElementAt(index);
  313. if (bitIndex >= capacity) continue;
  314. data |= 1u << (int)bitIndex;
  315. }
  316. }
  317. /// <summary>
  318. /// Bit-wise And
  319. /// </summary>
  320. /// <param name="other">Bit array with which to do the operation.</param>
  321. /// <returns>The resulting bit array.</returns>
  322. public IBitArray BitAnd(IBitArray other) => this & (BitArray32)other;
  323. /// <summary>
  324. /// Bit-wise Or
  325. /// </summary>
  326. /// <param name="other">Bit array with which to do the operation.</param>
  327. /// <returns>The resulting bit array.</returns>
  328. public IBitArray BitOr(IBitArray other) => this | (BitArray32)other;
  329. /// <summary>
  330. /// Bit-wise Not
  331. /// </summary>
  332. /// <returns>The resulting bit array.</returns>
  333. public IBitArray BitNot() => ~this;
  334. /// <summary>
  335. /// Bit-wise Not operator
  336. /// </summary>
  337. /// <param name="a">Bit array with which to do the operation.</param>
  338. /// <returns>The resulting bit array.</returns>
  339. public static BitArray32 operator ~(BitArray32 a) => new BitArray32(~a.data);
  340. /// <summary>
  341. /// Bit-wise Or operator
  342. /// </summary>
  343. /// <param name="a">First bit array.</param>
  344. /// <param name="b">Second bit array.</param>
  345. /// <returns>The resulting bit array.</returns>
  346. public static BitArray32 operator |(BitArray32 a, BitArray32 b) => new BitArray32(a.data | b.data);
  347. /// <summary>
  348. /// Bit-wise And operator
  349. /// </summary>
  350. /// <param name="a">First bit array.</param>
  351. /// <param name="b">Second bit array.</param>
  352. /// <returns>The resulting bit array.</returns>
  353. public static BitArray32 operator &(BitArray32 a, BitArray32 b) => new BitArray32(a.data & b.data);
  354. /// <summary>
  355. /// Equality operator.
  356. /// </summary>
  357. /// <param name="a">First bit array.</param>
  358. /// <param name="b">Second bit array.</param>
  359. /// <returns>True if both bit arrays are equals.</returns>
  360. public static bool operator ==(BitArray32 a, BitArray32 b) => a.data == b.data;
  361. /// <summary>
  362. /// Inequality operator.
  363. /// </summary>
  364. /// <param name="a">First bit array.</param>
  365. /// <param name="b">Second bit array.</param>
  366. /// <returns>True if the bit arrays are not equals.</returns>
  367. public static bool operator !=(BitArray32 a, BitArray32 b) => a.data != b.data;
  368. /// <summary>
  369. /// Equality operator.
  370. /// </summary>
  371. /// <param name="obj">Bit array to compare to.</param>
  372. /// <returns>True if the provided bit array is equal to this..</returns>
  373. public override bool Equals(object obj) => obj is BitArray32 && ((BitArray32)obj).data == data;
  374. /// <summary>
  375. /// Get the hashcode of the bit array.
  376. /// </summary>
  377. /// <returns>Hashcode of the bit array.</returns>
  378. public override int GetHashCode() => 1768953197 + data.GetHashCode();
  379. }
  380. /// <summary>
  381. /// Bit array of size 64.
  382. /// </summary>
  383. [Serializable]
  384. [System.Diagnostics.DebuggerDisplay("{this.GetType().Name} {humanizedData}")]
  385. public struct BitArray64 : IBitArray
  386. {
  387. [SerializeField]
  388. ulong data;
  389. /// <summary>Number of elements in the bit array.</summary>
  390. public uint capacity => 64u;
  391. /// <summary>True if all bits are 0.</summary>
  392. public bool allFalse => data == 0uL;
  393. /// <summary>True if all bits are 1.</summary>
  394. public bool allTrue => data == ulong.MaxValue;
  395. /// <summary>Returns the bit array in a human readable form.</summary>
  396. public string humanizedData => System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + capacity + "}", Convert.ToString((long)data, 2)).Replace(' ', '0'), ".{8}", "$0.").TrimEnd('.');
  397. /// <summary>
  398. /// Returns the state of the bit at a specific index.
  399. /// </summary>
  400. /// <param name="index">Index of the bit.</param>
  401. /// <returns>State of the bit at the provided index.</returns>
  402. public bool this[uint index]
  403. {
  404. get => BitArrayUtilities.Get64(index, data);
  405. set => BitArrayUtilities.Set64(index, ref data, value);
  406. }
  407. /// <summary>
  408. /// Constructor.
  409. /// </summary>
  410. /// <param name="initValue">Initialization value.</param>
  411. public BitArray64(ulong initValue) => data = initValue;
  412. /// <summary>
  413. /// Constructor.
  414. /// </summary>
  415. /// <param name="bitIndexTrue">List of indices where bits should be set to true.</param>
  416. public BitArray64(IEnumerable<uint> bitIndexTrue)
  417. {
  418. data = 0L;
  419. if (bitIndexTrue == null)
  420. return;
  421. for (int index = bitIndexTrue.Count() - 1; index >= 0; --index)
  422. {
  423. uint bitIndex = bitIndexTrue.ElementAt(index);
  424. if (bitIndex >= capacity) continue;
  425. data |= 1uL << (int)bitIndex;
  426. }
  427. }
  428. /// <summary>
  429. /// Bit-wise Not operator
  430. /// </summary>
  431. /// <param name="a">Bit array with which to do the operation.</param>
  432. /// <returns>The resulting bit array.</returns>
  433. public static BitArray64 operator ~(BitArray64 a) => new BitArray64(~a.data);
  434. /// <summary>
  435. /// Bit-wise Or operator
  436. /// </summary>
  437. /// <param name="a">First bit array.</param>
  438. /// <param name="b">Second bit array.</param>
  439. /// <returns>The resulting bit array.</returns>
  440. public static BitArray64 operator |(BitArray64 a, BitArray64 b) => new BitArray64(a.data | b.data);
  441. /// <summary>
  442. /// Bit-wise And operator
  443. /// </summary>
  444. /// <param name="a">First bit array.</param>
  445. /// <param name="b">Second bit array.</param>
  446. /// <returns>The resulting bit array.</returns>
  447. public static BitArray64 operator &(BitArray64 a, BitArray64 b) => new BitArray64(a.data & b.data);
  448. /// <summary>
  449. /// Bit-wise And
  450. /// </summary>
  451. /// <param name="other">Bit array with which to do the operation.</param>
  452. /// <returns>The resulting bit array.</returns>
  453. public IBitArray BitAnd(IBitArray other) => this & (BitArray64)other;
  454. /// <summary>
  455. /// Bit-wise Or
  456. /// </summary>
  457. /// <param name="other">Bit array with which to do the operation.</param>
  458. /// <returns>The resulting bit array.</returns>
  459. public IBitArray BitOr(IBitArray other) => this | (BitArray64)other;
  460. /// <summary>
  461. /// Bit-wise Not
  462. /// </summary>
  463. /// <returns>The resulting bit array.</returns>
  464. public IBitArray BitNot() => ~this;
  465. /// <summary>
  466. /// Equality operator.
  467. /// </summary>
  468. /// <param name="a">First bit array.</param>
  469. /// <param name="b">Second bit array.</param>
  470. /// <returns>True if both bit arrays are equals.</returns>
  471. public static bool operator ==(BitArray64 a, BitArray64 b) => a.data == b.data;
  472. /// <summary>
  473. /// Inequality operator.
  474. /// </summary>
  475. /// <param name="a">First bit array.</param>
  476. /// <param name="b">Second bit array.</param>
  477. /// <returns>True if the bit arrays are not equals.</returns>
  478. public static bool operator !=(BitArray64 a, BitArray64 b) => a.data != b.data;
  479. /// <summary>
  480. /// Equality operator.
  481. /// </summary>
  482. /// <param name="obj">Bit array to compare to.</param>
  483. /// <returns>True if the provided bit array is equal to this..</returns>
  484. public override bool Equals(object obj) => obj is BitArray64 && ((BitArray64)obj).data == data;
  485. /// <summary>
  486. /// Get the hashcode of the bit array.
  487. /// </summary>
  488. /// <returns>Hashcode of the bit array.</returns>
  489. public override int GetHashCode() => 1768953197 + data.GetHashCode();
  490. }
  491. /// <summary>
  492. /// Bit array of size 128.
  493. /// </summary>
  494. [Serializable]
  495. [System.Diagnostics.DebuggerDisplay("{this.GetType().Name} {humanizedData}")]
  496. public struct BitArray128 : IBitArray
  497. {
  498. [SerializeField]
  499. ulong data1;
  500. [SerializeField]
  501. ulong data2;
  502. /// <summary>Number of elements in the bit array.</summary>
  503. public uint capacity => 128u;
  504. /// <summary>True if all bits are 0.</summary>
  505. public bool allFalse => data1 == 0uL && data2 == 0uL;
  506. /// <summary>True if all bits are 1.</summary>
  507. public bool allTrue => data1 == ulong.MaxValue && data2 == ulong.MaxValue;
  508. /// <summary>Returns the bit array in a human readable form.</summary>
  509. public string humanizedData =>
  510. System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + 64u + "}", Convert.ToString((long)data2, 2)).Replace(' ', '0'), ".{8}", "$0.")
  511. + System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + 64u + "}", Convert.ToString((long)data1, 2)).Replace(' ', '0'), ".{8}", "$0.").TrimEnd('.');
  512. /// <summary>
  513. /// Returns the state of the bit at a specific index.
  514. /// </summary>
  515. /// <param name="index">Index of the bit.</param>
  516. /// <returns>State of the bit at the provided index.</returns>
  517. public bool this[uint index]
  518. {
  519. get => BitArrayUtilities.Get128(index, data1, data2);
  520. set => BitArrayUtilities.Set128(index, ref data1, ref data2, value);
  521. }
  522. /// <summary>
  523. /// Constructor.
  524. /// </summary>
  525. /// <param name="initValue1">Initialization value 1.</param>
  526. /// <param name="initValue2">Initialization value 2.</param>
  527. public BitArray128(ulong initValue1, ulong initValue2)
  528. {
  529. data1 = initValue1;
  530. data2 = initValue2;
  531. }
  532. /// <summary>
  533. /// Constructor.
  534. /// </summary>
  535. /// <param name="bitIndexTrue">List of indices where bits should be set to true.</param>
  536. public BitArray128(IEnumerable<uint> bitIndexTrue)
  537. {
  538. data1 = data2 = 0uL;
  539. if (bitIndexTrue == null)
  540. return;
  541. for (int index = bitIndexTrue.Count() - 1; index >= 0; --index)
  542. {
  543. uint bitIndex = bitIndexTrue.ElementAt(index);
  544. if (bitIndex < 64u)
  545. data1 |= 1uL << (int)bitIndex;
  546. else if (bitIndex < capacity)
  547. data2 |= 1uL << (int)(bitIndex - 64u);
  548. }
  549. }
  550. /// <summary>
  551. /// Bit-wise Not operator
  552. /// </summary>
  553. /// <param name="a">First bit array.</param>
  554. /// <returns>The resulting bit array.</returns>
  555. public static BitArray128 operator ~(BitArray128 a) => new BitArray128(~a.data1, ~a.data2);
  556. /// <summary>
  557. /// Bit-wise Or operator
  558. /// </summary>
  559. /// <param name="a">First bit array.</param>
  560. /// <param name="b">Second bit array.</param>
  561. /// <returns>The resulting bit array.</returns>
  562. public static BitArray128 operator |(BitArray128 a, BitArray128 b) => new BitArray128(a.data1 | b.data1, a.data2 | b.data2);
  563. /// <summary>
  564. /// Bit-wise And operator
  565. /// </summary>
  566. /// <param name="a">First bit array.</param>
  567. /// <param name="b">Second bit array.</param>
  568. /// <returns>The resulting bit array.</returns>
  569. public static BitArray128 operator &(BitArray128 a, BitArray128 b) => new BitArray128(a.data1 & b.data1, a.data2 & b.data2);
  570. /// <summary>
  571. /// Bit-wise And
  572. /// </summary>
  573. /// <param name="other">Bit array with which to do the operation.</param>
  574. /// <returns>The resulting bit array.</returns>
  575. public IBitArray BitAnd(IBitArray other) => this & (BitArray128)other;
  576. /// <summary>
  577. /// Bit-wise Or
  578. /// </summary>
  579. /// <param name="other">Bit array with which to do the operation.</param>
  580. /// <returns>The resulting bit array.</returns>
  581. public IBitArray BitOr(IBitArray other) => this | (BitArray128)other;
  582. /// <summary>
  583. /// Bit-wise Not
  584. /// </summary>
  585. /// <returns>The resulting bit array.</returns>
  586. public IBitArray BitNot() => ~this;
  587. /// <summary>
  588. /// Equality operator.
  589. /// </summary>
  590. /// <param name="a">First bit array.</param>
  591. /// <param name="b">Second bit array.</param>
  592. /// <returns>True if both bit arrays are equals.</returns>
  593. public static bool operator ==(BitArray128 a, BitArray128 b) => a.data1 == b.data1 && a.data2 == b.data2;
  594. /// <summary>
  595. /// Inequality operator.
  596. /// </summary>
  597. /// <param name="a">First bit array.</param>
  598. /// <param name="b">Second bit array.</param>
  599. /// <returns>True if the bit arrays are not equals.</returns>
  600. public static bool operator !=(BitArray128 a, BitArray128 b) => a.data1 != b.data1 || a.data2 != b.data2;
  601. /// <summary>
  602. /// Equality operator.
  603. /// </summary>
  604. /// <param name="obj">Bit array to compare to.</param>
  605. /// <returns>True if the provided bit array is equal to this..</returns>
  606. public override bool Equals(object obj) => (obj is BitArray128) && data1.Equals(((BitArray128)obj).data1) && data2.Equals(((BitArray128)obj).data2);
  607. /// <summary>
  608. /// Get the hashcode of the bit array.
  609. /// </summary>
  610. /// <returns>Hashcode of the bit array.</returns>
  611. public override int GetHashCode()
  612. {
  613. var hashCode = 1755735569;
  614. hashCode = hashCode * -1521134295 + data1.GetHashCode();
  615. hashCode = hashCode * -1521134295 + data2.GetHashCode();
  616. return hashCode;
  617. }
  618. }
  619. /// <summary>
  620. /// Bit array of size 256.
  621. /// </summary>
  622. [Serializable]
  623. [System.Diagnostics.DebuggerDisplay("{this.GetType().Name} {humanizedData}")]
  624. public struct BitArray256 : IBitArray
  625. {
  626. [SerializeField]
  627. ulong data1;
  628. [SerializeField]
  629. ulong data2;
  630. [SerializeField]
  631. ulong data3;
  632. [SerializeField]
  633. ulong data4;
  634. /// <summary>Number of elements in the bit array.</summary>
  635. public uint capacity => 256u;
  636. /// <summary>True if all bits are 0.</summary>
  637. public bool allFalse => data1 == 0uL && data2 == 0uL && data3 == 0uL && data4 == 0uL;
  638. /// <summary>True if all bits are 1.</summary>
  639. public bool allTrue => data1 == ulong.MaxValue && data2 == ulong.MaxValue && data3 == ulong.MaxValue && data4 == ulong.MaxValue;
  640. /// <summary>Returns the bit array in a human readable form.</summary>
  641. public string humanizedData =>
  642. System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + 64u + "}", Convert.ToString((long)data4, 2)).Replace(' ', '0'), ".{8}", "$0.")
  643. + System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + 64u + "}", Convert.ToString((long)data3, 2)).Replace(' ', '0'), ".{8}", "$0.")
  644. + System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + 64u + "}", Convert.ToString((long) data2, 2)).Replace(' ', '0'), ".{8}", "$0.")
  645. + System.Text.RegularExpressions.Regex.Replace(String.Format("{0, " + 64u + "}", Convert.ToString((long) data1, 2)).Replace(' ', '0'), ".{8}", "$0.").TrimEnd('.');
  646. /// <summary>
  647. /// Returns the state of the bit at a specific index.
  648. /// </summary>
  649. /// <param name="index">Index of the bit.</param>
  650. /// <returns>State of the bit at the provided index.</returns>
  651. public bool this[uint index]
  652. {
  653. get => BitArrayUtilities.Get256(index, data1, data2, data3, data4);
  654. set => BitArrayUtilities.Set256(index, ref data1, ref data2, ref data3, ref data4, value);
  655. }
  656. /// <summary>
  657. /// Constructor.
  658. /// </summary>
  659. /// <param name="initValue1">Initialization value 1.</param>
  660. /// <param name="initValue2">Initialization value 2.</param>
  661. /// <param name="initValue3">Initialization value 3.</param>
  662. /// <param name="initValue4">Initialization value 4.</param>
  663. public BitArray256(ulong initValue1, ulong initValue2, ulong initValue3, ulong initValue4)
  664. {
  665. data1 = initValue1;
  666. data2 = initValue2;
  667. data3 = initValue3;
  668. data4 = initValue4;
  669. }
  670. /// <summary>
  671. /// Constructor.
  672. /// </summary>
  673. /// <param name="bitIndexTrue">List of indices where bits should be set to true.</param>
  674. public BitArray256(IEnumerable<uint> bitIndexTrue)
  675. {
  676. data1 = data2 = data3 = data4 = 0uL;
  677. if (bitIndexTrue == null)
  678. return;
  679. for (int index = bitIndexTrue.Count() - 1; index >= 0; --index)
  680. {
  681. uint bitIndex = bitIndexTrue.ElementAt(index);
  682. if (bitIndex < 64u)
  683. data1 |= 1uL << (int)bitIndex;
  684. else if (bitIndex < 128u)
  685. data2 |= 1uL << (int)(bitIndex - 64u);
  686. else if (bitIndex < 192u)
  687. data3 |= 1uL << (int)(bitIndex - 128u);
  688. else if (bitIndex < capacity)
  689. data4 |= 1uL << (int)(bitIndex - 192u);
  690. }
  691. }
  692. /// <summary>
  693. /// Bit-wise Not operator
  694. /// </summary>
  695. /// <param name="a">Bit array with which to do the operation.</param>
  696. /// <returns>The resulting bit array.</returns>
  697. public static BitArray256 operator ~(BitArray256 a) => new BitArray256(~a.data1, ~a.data2, ~a.data3, ~a.data4);
  698. /// <summary>
  699. /// Bit-wise Or operator
  700. /// </summary>
  701. /// <param name="a">First bit array.</param>
  702. /// <param name="b">Second bit array.</param>
  703. /// <returns>The resulting bit array.</returns>
  704. public static BitArray256 operator |(BitArray256 a, BitArray256 b) => new BitArray256(a.data1 | b.data1, a.data2 | b.data2, a.data3 | b.data3, a.data4 | b.data4);
  705. /// <summary>
  706. /// Bit-wise And operator
  707. /// </summary>
  708. /// <param name="a">First bit array.</param>
  709. /// <param name="b">Second bit array.</param>
  710. /// <returns>The resulting bit array.</returns>
  711. public static BitArray256 operator &(BitArray256 a, BitArray256 b) => new BitArray256(a.data1 & b.data1, a.data2 & b.data2, a.data3 & b.data3, a.data4 & b.data4);
  712. /// <summary>
  713. /// Bit-wise And
  714. /// </summary>
  715. /// <param name="other">Bit array with which to do the operation.</param>
  716. /// <returns>The resulting bit array.</returns>
  717. public IBitArray BitAnd(IBitArray other) => this & (BitArray256)other;
  718. /// <summary>
  719. /// Bit-wise Or
  720. /// </summary>
  721. /// <param name="other">Bit array with which to do the operation.</param>
  722. /// <returns>The resulting bit array.</returns>
  723. public IBitArray BitOr(IBitArray other) => this | (BitArray256)other;
  724. /// <summary>
  725. /// Bit-wise Not
  726. /// </summary>
  727. /// <returns>The resulting bit array.</returns>
  728. public IBitArray BitNot() => ~this;
  729. /// <summary>
  730. /// Equality operator.
  731. /// </summary>
  732. /// <param name="a">First bit array.</param>
  733. /// <param name="b">Second bit array.</param>
  734. /// <returns>True if both bit arrays are equals.</returns>
  735. public static bool operator ==(BitArray256 a, BitArray256 b) => a.data1 == b.data1 && a.data2 == b.data2 && a.data3 == b.data3 && a.data4 == b.data4;
  736. /// <summary>
  737. /// Inequality operator.
  738. /// </summary>
  739. /// <param name="a">First bit array.</param>
  740. /// <param name="b">Second bit array.</param>
  741. /// <returns>True if the bit arrays are not equals.</returns>
  742. public static bool operator !=(BitArray256 a, BitArray256 b) => a.data1 != b.data1 || a.data2 != b.data2 || a.data3 != b.data3 || a.data4 != b.data4;
  743. /// <summary>
  744. /// Equality operator.
  745. /// </summary>
  746. /// <param name="obj">Bit array to compare to.</param>
  747. /// <returns>True if the provided bit array is equal to this..</returns>
  748. public override bool Equals(object obj) =>
  749. (obj is BitArray256)
  750. && data1.Equals(((BitArray256)obj).data1)
  751. && data2.Equals(((BitArray256)obj).data2)
  752. && data3.Equals(((BitArray256)obj).data3)
  753. && data4.Equals(((BitArray256)obj).data4);
  754. /// <summary>
  755. /// Get the hashcode of the bit array.
  756. /// </summary>
  757. /// <returns>Hashcode of the bit array.</returns>
  758. public override int GetHashCode()
  759. {
  760. var hashCode = 1870826326;
  761. hashCode = hashCode * -1521134295 + data1.GetHashCode();
  762. hashCode = hashCode * -1521134295 + data2.GetHashCode();
  763. hashCode = hashCode * -1521134295 + data3.GetHashCode();
  764. hashCode = hashCode * -1521134295 + data4.GetHashCode();
  765. return hashCode;
  766. }
  767. }
  768. /// <summary>
  769. /// Bit array utility class.
  770. /// </summary>
  771. public static class BitArrayUtilities
  772. {
  773. //written here to not duplicate the serialized accessor and runtime accessor
  774. /// <summary>
  775. /// Get a bit at a specific index.
  776. /// </summary>
  777. /// <param name="index">Bit index.</param>
  778. /// <param name="data">Bit array data.</param>
  779. /// <returns>The value of the bit at the specific index.</returns>
  780. public static bool Get8(uint index, byte data) => (data & (1u << (int)index)) != 0u;
  781. /// <summary>
  782. /// Get a bit at a specific index.
  783. /// </summary>
  784. /// <param name="index">Bit index.</param>
  785. /// <param name="data">Bit array data.</param>
  786. /// <returns>The value of the bit at the specific index.</returns>
  787. public static bool Get16(uint index, ushort data) => (data & (1u << (int)index)) != 0u;
  788. /// <summary>
  789. /// Get a bit at a specific index.
  790. /// </summary>
  791. /// <param name="index">Bit index.</param>
  792. /// <param name="data">Bit array data.</param>
  793. /// <returns>The value of the bit at the specific index.</returns>
  794. public static bool Get32(uint index, uint data) => (data & (1u << (int)index)) != 0u;
  795. /// <summary>
  796. /// Get a bit at a specific index.
  797. /// </summary>
  798. /// <param name="index">Bit index.</param>
  799. /// <param name="data">Bit array data.</param>
  800. /// <returns>The value of the bit at the specific index.</returns>
  801. public static bool Get64(uint index, ulong data) => (data & (1uL << (int)index)) != 0uL;
  802. /// <summary>
  803. /// Get a bit at a specific index.
  804. /// </summary>
  805. /// <param name="index">Bit index.</param>
  806. /// <param name="data1">Bit array data 1.</param>
  807. /// <param name="data2">Bit array data 2.</param>
  808. /// <returns>The value of the bit at the specific index.</returns>
  809. public static bool Get128(uint index, ulong data1, ulong data2)
  810. => index < 64u
  811. ? (data1 & (1uL << (int)index)) != 0uL
  812. : (data2 & (1uL << (int)(index - 64u))) != 0uL;
  813. /// <summary>
  814. /// Get a bit at a specific index.
  815. /// </summary>
  816. /// <param name="index">Bit index.</param>
  817. /// <param name="data1">Bit array data 1.</param>
  818. /// <param name="data2">Bit array data 2.</param>
  819. /// <param name="data3">Bit array data 3.</param>
  820. /// <param name="data4">Bit array data 4.</param>
  821. /// <returns>The value of the bit at the specific index.</returns>
  822. public static bool Get256(uint index, ulong data1, ulong data2, ulong data3, ulong data4)
  823. => index < 128u
  824. ? index < 64u
  825. ? (data1 & (1uL << (int)index)) != 0uL
  826. : (data2 & (1uL << (int)(index - 64u))) != 0uL
  827. : index < 192u
  828. ? (data3 & (1uL << (int)(index - 128u))) != 0uL
  829. : (data4 & (1uL << (int)(index - 192u))) != 0uL;
  830. /// <summary>
  831. /// Set a bit at a specific index.
  832. /// </summary>
  833. /// <param name="index">Bit index.</param>
  834. /// <param name="data">Bit array data.</param>
  835. /// <param name="value">Value to set the bit to.</param>
  836. public static void Set8(uint index, ref byte data, bool value) => data = (byte)(value ? (data | (1u << (int)index)) : (data & ~(1u << (int)index)));
  837. /// <summary>
  838. /// Set a bit at a specific index.
  839. /// </summary>
  840. /// <param name="index">Bit index.</param>
  841. /// <param name="data">Bit array data.</param>
  842. /// <param name="value">Value to set the bit to.</param>
  843. public static void Set16(uint index, ref ushort data, bool value) => data = (ushort)(value ? (data | (1u << (int)index)) : (data & ~(1u << (int)index)));
  844. /// <summary>
  845. /// Set a bit at a specific index.
  846. /// </summary>
  847. /// <param name="index">Bit index.</param>
  848. /// <param name="data">Bit array data.</param>
  849. /// <param name="value">Value to set the bit to.</param>
  850. public static void Set32(uint index, ref uint data, bool value) => data = (value ? (data | (1u << (int)index)) : (data & ~(1u << (int)index)));
  851. /// <summary>
  852. /// Set a bit at a specific index.
  853. /// </summary>
  854. /// <param name="index">Bit index.</param>
  855. /// <param name="data">Bit array data.</param>
  856. /// <param name="value">Value to set the bit to.</param>
  857. public static void Set64(uint index, ref ulong data, bool value) => data = (value ? (data | (1uL << (int)index)) : (data & ~(1uL << (int)index)));
  858. /// <summary>
  859. /// Set a bit at a specific index.
  860. /// </summary>
  861. /// <param name="index">Bit index.</param>
  862. /// <param name="data1">Bit array data 1.</param>
  863. /// <param name="data2">Bit array data 2.</param>
  864. /// <param name="value">Value to set the bit to.</param>
  865. public static void Set128(uint index, ref ulong data1, ref ulong data2, bool value)
  866. {
  867. if (index < 64u)
  868. data1 = (value ? (data1 | (1uL << (int)index)) : (data1 & ~(1uL << (int)index)));
  869. else
  870. data2 = (value ? (data2 | (1uL << (int)(index - 64u))) : (data2 & ~(1uL << (int)(index - 64u))));
  871. }
  872. /// <summary>
  873. /// Set a bit at a specific index.
  874. /// </summary>
  875. /// <param name="index">Bit index.</param>
  876. /// <param name="data1">Bit array data 1.</param>
  877. /// <param name="data2">Bit array data 2.</param>
  878. /// <param name="data3">Bit array data 3.</param>
  879. /// <param name="data4">Bit array data 4.</param>
  880. /// <param name="value">Value to set the bit to.</param>
  881. public static void Set256(uint index, ref ulong data1, ref ulong data2, ref ulong data3, ref ulong data4, bool value)
  882. {
  883. if (index < 64u)
  884. data1 = (value ? (data1 | (1uL << (int)index)) : (data1 & ~(1uL << (int)index)));
  885. else if (index < 128u)
  886. data2 = (value ? (data2 | (1uL << (int)(index - 64u))) : (data2 & ~(1uL << (int)(index - 64u))));
  887. else if (index < 192u)
  888. data3 = (value ? (data3 | (1uL << (int)(index - 64u))) : (data3 & ~(1uL << (int)(index - 128u))));
  889. else
  890. data4 = (value ? (data4 | (1uL << (int)(index - 64u))) : (data4 & ~(1uL << (int)(index - 192u))));
  891. }
  892. }
  893. }