Array4.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <cstddef>
  9. #include <vector>
  10. // The Array4 class represents a 4-dimensional array that minimizes the number
  11. // of new and delete calls. The T objects are stored in a contiguous array.
  12. namespace WwiseGTE
  13. {
  14. template <typename T>
  15. class Array4
  16. {
  17. public:
  18. // Construction. The first constructor generates an array of objects
  19. // that are owned by Array4. The second constructor is given an array
  20. // of objects that are owned by the caller. The array has bound0
  21. // columns, bound1 rows, bound2 slices, and bound3 cuboids.
  22. Array4(size_t bound0, size_t bound1, size_t bound2, size_t bound3)
  23. :
  24. mBound0(bound0),
  25. mBound1(bound1),
  26. mBound2(bound2),
  27. mBound3(bound3),
  28. mObjects(bound0 * bound1 * bound2 * bound3),
  29. mIndirect1(bound1 * bound2 * bound3),
  30. mIndirect2(bound2 * bound3),
  31. mIndirect3(bound3)
  32. {
  33. SetPointers(mObjects.data());
  34. }
  35. Array4(size_t bound0, size_t bound1, size_t bound2, size_t bound3, T* objects)
  36. :
  37. mBound0(bound0),
  38. mBound1(bound1),
  39. mBound2(bound2),
  40. mBound3(bound3),
  41. mIndirect1(bound1 * bound2 * bound3),
  42. mIndirect2(bound2 * bound3),
  43. mIndirect3(bound3)
  44. {
  45. SetPointers(objects);
  46. }
  47. // Support for dynamic resizing, copying, or moving. If 'other' does
  48. // not own the original 'objects', they are not copied by the
  49. // assignment operator.
  50. Array4()
  51. :
  52. mBound0(0),
  53. mBound1(0),
  54. mBound2(0),
  55. mBound3(0)
  56. {
  57. }
  58. Array4(Array4 const& other)
  59. :
  60. mBound0(other.mBound0),
  61. mBound1(other.mBound1),
  62. mBound2(other.mBound2),
  63. mBound3(other.mBound3)
  64. {
  65. *this = other;
  66. }
  67. Array4& operator=(Array4 const& other)
  68. {
  69. // The copy is valid whether or not other.mObjects has elements.
  70. mObjects = other.mObjects;
  71. SetPointers(other);
  72. return *this;
  73. }
  74. Array4(Array4&& other) noexcept
  75. :
  76. mBound0(other.mBound0),
  77. mBound1(other.mBound1),
  78. mBound2(other.mBound2),
  79. mBound3(other.mBound3)
  80. {
  81. *this = std::move(other);
  82. }
  83. Array4& operator=(Array4&& other) noexcept
  84. {
  85. // The move is valid whether or not other.mObjects has elements.
  86. mObjects = std::move(other.mObjects);
  87. SetPointers(other);
  88. return *this;
  89. }
  90. // Access to the array. Sample usage is
  91. // Array4<T> myArray(5, 4, 3, 2);
  92. // T*** cuboid1 = myArray[1];
  93. // T** cuboid1Slice2 = myArray[1][2];
  94. // T* cuboid1Slice2Row3 = myArray[1][2][3];
  95. // T cuboid1Slice2Row3Col4 = myArray[1][2][3][4];
  96. inline size_t GetBound0() const
  97. {
  98. return mBound0;
  99. }
  100. inline size_t GetBound1() const
  101. {
  102. return mBound1;
  103. }
  104. inline size_t GetBound2() const
  105. {
  106. return mBound2;
  107. }
  108. inline size_t GetBound3() const
  109. {
  110. return mBound3;
  111. }
  112. inline T** const* operator[](int cuboid) const
  113. {
  114. return mIndirect3[cuboid];
  115. }
  116. inline T*** operator[](int cuboid)
  117. {
  118. return mIndirect3[cuboid];
  119. }
  120. private:
  121. void SetPointers(T* objects)
  122. {
  123. for (size_t i3 = 0; i3 < mBound3; ++i3)
  124. {
  125. size_t j2 = mBound2 * i3; // = bound2*(i3 + j3) where j3 = 0
  126. mIndirect3[i3] = &mIndirect2[j2];
  127. for (size_t i2 = 0; i2 < mBound2; ++i2)
  128. {
  129. size_t j1 = mBound1 * (i2 + j2);
  130. mIndirect3[i3][i2] = &mIndirect1[j1];
  131. for (size_t i1 = 0; i1 < mBound1; ++i1)
  132. {
  133. size_t j0 = mBound0 * (i1 + j1);
  134. mIndirect3[i3][i2][i1] = &objects[j0];
  135. }
  136. }
  137. }
  138. }
  139. void SetPointers(Array4 const& other)
  140. {
  141. mBound0 = other.mBound0;
  142. mBound1 = other.mBound1;
  143. mBound2 = other.mBound2;
  144. mBound3 = other.mBound3;
  145. mIndirect1.resize(mBound1 * mBound2 * mBound3);
  146. mIndirect2.resize(mBound2 * mBound3);
  147. mIndirect3.resize(mBound3);
  148. if (mBound0 > 0)
  149. {
  150. // The objects are owned.
  151. SetPointers(mObjects.data());
  152. }
  153. else if (mIndirect1.size() > 0)
  154. {
  155. // The objects are not owned.
  156. SetPointers(other.mIndirect3[0][0][0]);
  157. }
  158. // else 'other' is an empty Array3.
  159. }
  160. size_t mBound0, mBound1, mBound2, mBound3;
  161. std::vector<T> mObjects;
  162. std::vector<T*> mIndirect1;
  163. std::vector<T**> mIndirect2;
  164. std::vector<T***> mIndirect3;
  165. };
  166. }