TBTK
Need a break? Support the development by playing Polarity Puzzles
ArrayManager.h
1 /* Copyright 2016 Kristofer Björnson
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
17 
24 #ifndef COM_DAFER45_TBTK_ARRAY_MANAGER
25 #define COM_DAFER45_TBTK_ARRAY_MANAGER
26 
27 #include "TBTK/Index.h"
28 #include "TBTK/Streams.h"
29 
30 namespace TBTK{
31 
38 template<typename T>
39 class ArrayManager{
40 public:
42  static void* create(const Index &ranges);
43 
45  static void* create(const Index &ranges, T fill);
46 
48  static void destroy(void *array, const Index &ranges);
49 
51  static T* flatten(void *array, const Index &ranges);
52 
54  static void* unflatten(T *array, const Index &ranges);
55 
57  static void print(void * array, const Index &ranges);
58 private:
60  static void createRecursive(Index ranges, void **result);
61 
63  static void createRecursive(Index ranges, void **result, T fill);
64 
66  static void destroyRecursive(void *array, Index ranges);
67 
69  static void flattenRecursive(void *array, Index ranges, T *result, int offset);
70 
72  static void unflattenRecursive(T *array, Index ranges, void **result, int offset);
73 
75  static void printRecursive(void *array, Index ranges);
76 };
77 
78 template<typename T>
79 void* ArrayManager<T>::create(const Index &ranges){
80  void *result;
81 
82  createRecursive(ranges, &result);
83 
84  return result;
85 }
86 
87 template<typename T>
88 void ArrayManager<T>::createRecursive(Index ranges, void **result){
89  if(ranges.getSize() == 1){
90  *((T**)result) = new T[ranges.at(0)];
91  }
92  else{
93  *((void**)result) = new void*[ranges.at(0)];
94 
95  int currentRange = ranges.at(0);
96 // ranges.erase(ranges.begin());
97  ranges.popFront();
98  for(int n = 0; n < currentRange; n++)
99  createRecursive(ranges, &(((void**)(*result))[n]));
100  }
101 }
102 
103 template<typename T>
104 void* ArrayManager<T>::create(const Index &ranges, T fill){
105  void *result;
106 
107  createRecursive(ranges, &result, fill);
108 
109  return result;
110 }
111 
112 template<typename T>
113 void ArrayManager<T>::createRecursive(Index ranges, void **result, T fill){
114  if(ranges.getSize() == 1){
115  *((T**)result) = new T[ranges.at(0)];
116  for(int n = 0; n < ranges.at(0); n++)
117  (*((T**)result))[n] = fill;
118  }
119  else{
120  *((void**)result) = new void*[ranges.at(0)];
121 
122  int currentRange = ranges.at(0);
123 // ranges.erase(ranges.begin());
124  ranges.popFront();
125  for(int n = 0; n < currentRange; n++)
126  createRecursive(ranges, &(((void**)(*result))[n]), fill);
127  }
128 }
129 
130 template<typename T>
131 void ArrayManager<T>::destroy(void *array, const Index &ranges){
132  destroyRecursive(array, ranges);
133 }
134 
135 template<typename T>
136 void ArrayManager<T>::destroyRecursive(void *array, Index ranges){
137  if(ranges.getSize() == 1){
138  delete [] (T*)array;
139  }
140  else{
141  int currentRange = ranges.at(0);
142 // ranges.erase(ranges.begin());
143  ranges.popFront();
144  for(int n = 0; n < currentRange; n++)
145  destroyRecursive(((void**)array)[n], ranges);
146 
147  delete [] (void**)array;
148  }
149 }
150 
151 template<typename T>
152 T* ArrayManager<T>::flatten(void *array, const Index &ranges){
153  int size = 1;
154  for(unsigned int n = 0; n < ranges.getSize(); n++)
155  size *= ranges.at(n);
156 
157  T *result = new T[size];
158 
159  flattenRecursive(array, ranges, result, 0);
160 
161  return result;
162 }
163 
164 template<typename T>
165 void ArrayManager<T>::flattenRecursive(void *array, Index ranges, T *result, int offset){
166  if(ranges.getSize() == 1){
167  for(int n = 0; n < ranges.at(0); n++){
168  result[offset + n] = ((T*)array)[n];
169  }
170  }
171  else{
172  int offsetMultiplier = 1;
173  for(unsigned int n = 1; n < ranges.getSize(); n++)
174  offsetMultiplier *= ranges.at(n);
175 
176  int currentRange = ranges.at(0);
177 // ranges.erase(ranges.begin());
178  ranges.popFront();
179  for(int n = 0; n < currentRange; n++)
180  flattenRecursive(((void**)array)[n], ranges, result, offset + offsetMultiplier*n);
181  }
182 }
183 
184 template<typename T>
185 void* ArrayManager<T>::unflatten(T *array, const Index &ranges){
186  void *result;
187 
188  unflattenRecursive(array, ranges, &result, 0);
189 
190  return (void*)result;
191 }
192 
193 template<typename T>
194 void ArrayManager<T>::unflattenRecursive(T *array, Index ranges, void **result, int offset){
195  if(ranges.getSize() == 1){
196  *((T**)result) = new T[ranges.at(0)];
197  for(int n = 0; n < ranges.at(0); n++)
198  (*((T**)result))[n] = array[offset + n];
199  }
200  else{
201  *((void**)result) = new void*[ranges.at(0)];
202 
203  int offsetMultiplier = 1;
204  for(int n = 1; n < ranges.getSize(); n++)
205  offsetMultiplier *= ranges.at(n);
206 
207  int currentRange = ranges.at(0);
208 // ranges.erase(ranges.begin());
209  ranges.popFront();
210  for(int n = 0; n < currentRange; n++)
211  unflattenRecursive(array, ranges, &(((void**)(*result))[n]), offset + offsetMultiplier*n);
212  }
213 }
214 
215 template<typename T>
216 void ArrayManager<T>::print(void *array, const Index &ranges){
217  printRecursive(array, ranges);
218 }
219 
220 template<typename T>
221 void ArrayManager<T>::printRecursive(void *array, Index ranges){
222  if(ranges.getSize() == 1){
223  for(int n = 0; n < ranges.at(0); n++)
224  Streams::out << ((T*)array)[n] << "\t";
225  Streams::out << "\n";
226  }
227  else{
228  int currentRange = ranges.at(0);
229  ranges.popFront();
230  for(int n = 0; n < currentRange; n++)
231  printRecursive(((void**)array)[n], ranges);
232  Streams::out << "\n";
233  }
234 }
235 
236 }; //End of namespace TBTK
237 
238 #endif
239 
Physical index.
static std::ostream out
Definition: Streams.h:70
Definition: Boolean.h:32
Streams for TBTK output.