1 |
|
/** |
2 |
|
* HMLP (High-Performance Machine Learning Primitives) |
3 |
|
* |
4 |
|
* Copyright (C) 2014-2017, The University of Texas at Austin |
5 |
|
* |
6 |
|
* This program is free software: you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
8 |
|
* the Free Software Foundation, either version 3 of the License, or |
9 |
|
* (at your option) any later version. |
10 |
|
* |
11 |
|
* This program is distributed in the hope that it will be useful, |
12 |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
* GNU General Public License for more details. |
15 |
|
* |
16 |
|
* You should have received a copy of the GNU General Public License |
17 |
|
* along with this program. If not, see the LICENSE file. |
18 |
|
* |
19 |
|
**/ |
20 |
|
|
21 |
|
|
22 |
|
|
23 |
|
|
24 |
|
#ifndef VIEW_HPP |
25 |
|
#define VIEW_HPP |
26 |
|
|
27 |
|
#include <Data.hpp> |
28 |
|
|
29 |
|
using namespace std; |
30 |
|
using namespace hmlp; |
31 |
|
|
32 |
|
namespace hmlp |
33 |
|
{ |
34 |
|
|
35 |
|
typedef enum { TRANSPOSE, NOTRANSPOSE } TransposeType; |
36 |
|
/** 1x2, 2x1, 1x3, 3x1 */ |
37 |
|
typedef enum { LEFT, RIGHT, BOTTOM, TOP } SideType; |
38 |
|
/** 2x2, 3x3 */ |
39 |
|
typedef enum { TOPLEFT, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT } QuadrantType; |
40 |
|
|
41 |
|
|
42 |
|
template<typename T> |
43 |
|
class View : public ReadWrite |
44 |
|
{ |
45 |
|
public: |
46 |
|
|
47 |
|
/** empty constructor */ |
48 |
|
View() {}; |
49 |
|
|
50 |
|
/** constructor for the buffer */ |
51 |
|
View( Data<T> &buff ) { Set( buff ); }; |
52 |
|
|
53 |
|
View( bool TRANS, Data<T> &buff ) { Set( TRANS, buff ); }; |
54 |
|
|
55 |
|
|
56 |
|
/** destructor */ |
57 |
|
//~View() { printf( "~View()\n" ); fflush( stdout ); }; |
58 |
|
|
59 |
|
/** base case setup */ |
60 |
|
void Set( bool TRANS, Data<T> &buff ) |
61 |
|
{ |
62 |
|
this->trans = TRANS; |
63 |
|
if ( trans ) |
64 |
|
{ |
65 |
|
/** Data<T> is stored in column major */ |
66 |
|
this->m = buff.col(); |
67 |
|
this->n = buff.row(); |
68 |
|
} |
69 |
|
else |
70 |
|
{ |
71 |
|
this->m = buff.row(); |
72 |
|
this->n = buff.col(); |
73 |
|
} |
74 |
|
this->offm = 0; |
75 |
|
this->offn = 0; |
76 |
|
this->base = this; |
77 |
|
this->buff = &buff; |
78 |
|
}; |
79 |
|
|
80 |
|
/** (Default) is none transpose. */ |
81 |
|
void Set( Data<T> &buff ) { Set( false, buff ); }; |
82 |
|
|
83 |
|
/** non-base case setup */ |
84 |
|
void Set( size_t m, size_t n, size_t offm, size_t offn, View<T> *base ) |
85 |
|
{ |
86 |
|
this->trans = base->trans; |
87 |
|
if ( trans ) |
88 |
|
{ |
89 |
|
assert( offm <= base->buff->col() ); |
90 |
|
assert( offn <= base->buff->row() ); |
91 |
|
} |
92 |
|
else |
93 |
|
{ |
94 |
|
assert( offm <= base->buff->row() ); |
95 |
|
assert( offn <= base->buff->col() ); |
96 |
|
} |
97 |
|
this->m = m; |
98 |
|
this->n = n; |
99 |
|
this->offm = offm; |
100 |
|
this->offn = offn; |
101 |
|
this->base = base; |
102 |
|
this->buff = base->buff; |
103 |
|
}; |
104 |
|
|
105 |
|
/** subview operator */ |
106 |
|
template<typename TINDEX> |
107 |
|
T & operator () ( TINDEX i, TINDEX j ) |
108 |
|
{ |
109 |
|
size_t offset = 0; |
110 |
|
if ( trans ) |
111 |
|
{ |
112 |
|
assert( offm + i < buff->col() ); |
113 |
|
assert( offn + j < buff->row() ); |
114 |
|
offset = i * ld() + j; |
115 |
|
} |
116 |
|
else |
117 |
|
{ |
118 |
|
assert( offm + i < buff->row() ); |
119 |
|
assert( offn + j < buff->col() ); |
120 |
|
offset = j * ld() + i; |
121 |
|
} |
122 |
|
return *( data() + offset ); |
123 |
|
}; |
124 |
|
|
125 |
|
void CopyValuesFrom( View<T> & A ) |
126 |
|
{ |
127 |
|
if ( !m || !n ) return; |
128 |
|
assert( A.row() == m && A.col() == n ); |
129 |
|
for ( size_t j = 0; j < n; j ++ ) |
130 |
|
for ( size_t i = 0; i < m; i ++ ) |
131 |
|
(*this)( i, j ) = A( i, j ); |
132 |
|
}; |
133 |
|
|
134 |
|
void CopyValuesFrom( Data<T> & A ) |
135 |
|
{ |
136 |
|
if ( !m || !n ) return; |
137 |
|
assert( A.row() == m && A.col() == n ); |
138 |
|
for ( size_t j = 0; j < n; j ++ ) |
139 |
|
for ( size_t i = 0; i < m; i ++ ) |
140 |
|
(*this)( i, j ) = A( i, j ); |
141 |
|
}; |
142 |
|
|
143 |
|
/** Return a data copy of the subview */ |
144 |
|
Data<T> toData() |
145 |
|
{ |
146 |
|
Data<T> A( m, n ); |
147 |
|
for ( size_t j = 0; j < n; j ++ ) |
148 |
|
for ( size_t i = 0; i < m; i ++ ) |
149 |
|
A( i, j ) = (*this)( i, j ); |
150 |
|
return A; |
151 |
|
}; |
152 |
|
|
153 |
|
/** [ A1; = A |
154 |
|
* A2; ] */ |
155 |
|
void Partition2x1( View<T> &A1, |
156 |
|
View<T> &A2, size_t mb, SideType side ) |
157 |
|
{ |
158 |
|
/** readjust mb */ |
159 |
|
if ( mb > m ) mb = m; |
160 |
|
if ( side == BOTTOM ) mb = m - mb; |
161 |
|
/** setup A1 */ |
162 |
|
A1.Set( mb, this->n, this->offm, this->offn, this->base ); |
163 |
|
/** setup A2 */ |
164 |
|
A2.Set( m - mb, this->n, this->offm + mb, this->offn, this->base ); |
165 |
|
}; |
166 |
|
|
167 |
|
|
168 |
|
/** A = [ A1; |
169 |
|
* A2; ] */ |
170 |
|
void ContinueWith2x1( View<T> &A1, |
171 |
|
View<T> &A2 ) |
172 |
|
{ |
173 |
|
if ( A1.row() && A2.row() ) assert( A1.col() == A2.col() ); |
174 |
|
(*this) = A1; |
175 |
|
assert( A2.HasTheSameBuffer( this->buff ) ); |
176 |
|
this->m = A1.row() + A2.row(); |
177 |
|
}; |
178 |
|
|
179 |
|
/** [ A1, A2; ] = A */ |
180 |
|
void Partition1x2( View<T> &A1, View<T> &A2, size_t nb, SideType side ) |
181 |
|
{ |
182 |
|
/** readjust mb */ |
183 |
|
if ( nb > n ) nb = n; |
184 |
|
if ( side == RIGHT ) nb = n - nb; |
185 |
|
/** setup A1 */ |
186 |
|
A1.Set( this->m, nb, this->offm, this->offn, this->base ); |
187 |
|
/** setup A2 */ |
188 |
|
A2.Set( this->m, n - nb, this->offm, this->offn + nb, this->base ); |
189 |
|
}; |
190 |
|
|
191 |
|
/** A = [ A1, A2; ] */ |
192 |
|
void ContinueWith1x2( View<T> &A1, View<T> &A2 ) |
193 |
|
{ |
194 |
|
if ( A1.col() && A2.col() ) assert( A1.row() == A2.row() ); |
195 |
|
(*this) = A1; |
196 |
|
assert( A2.HasTheSameBuffer( this->buff ) ); |
197 |
|
this->n = A1.col() + A2.col(); |
198 |
|
}; |
199 |
|
|
200 |
|
/** A = [ A11, A12; A21, A22; ]; */ |
201 |
|
void Partition2x2 ( View<T> &A11, View<T> &A12, |
202 |
|
View<T> &A21, View<T> &A22, |
203 |
|
size_t mb, size_t nb, QuadrantType quadrant ) |
204 |
|
{ |
205 |
|
if ( mb > m ) mb = m; |
206 |
|
if ( nb > n ) nb = n; |
207 |
|
|
208 |
|
switch ( quadrant ) |
209 |
|
{ |
210 |
|
case TOPLEFT: |
211 |
|
{ |
212 |
|
break; |
213 |
|
} |
214 |
|
case TOPRIGHT: |
215 |
|
{ |
216 |
|
nb = n - nb; |
217 |
|
break; |
218 |
|
} |
219 |
|
case BOTTOMLEFT: |
220 |
|
{ |
221 |
|
mb = m - mb; |
222 |
|
break; |
223 |
|
} |
224 |
|
case BOTTOMRIGHT: |
225 |
|
{ |
226 |
|
mb = m - mb; |
227 |
|
nb = n - nb; |
228 |
|
break; |
229 |
|
} |
230 |
|
default: |
231 |
|
{ |
232 |
|
printf( "invalid quadrant\n" ); |
233 |
|
break; |
234 |
|
} |
235 |
|
} |
236 |
|
|
237 |
|
/** setup A11 */ |
238 |
|
A11.Set( mb, nb, offm , offn , this->base ); |
239 |
|
/** setup A12 */ |
240 |
|
A12.Set( mb, n - nb, offm , offn + nb, this->base ); |
241 |
|
/** setup A21 */ |
242 |
|
A21.Set( m - mb, nb, offm + mb, offn , this->base ); |
243 |
|
/** setup A22 */ |
244 |
|
A22.Set( m - mb, n - nb, offm + mb, offn + nb, this->base ); |
245 |
|
|
246 |
|
}; |
247 |
|
|
248 |
|
|
249 |
|
void ContinueWith2x2( View<T> &A11, View<T> &A12, |
250 |
|
View<T> &A21, View<T> &A22 ) |
251 |
|
{ |
252 |
|
assert( A11.row() == A12.row() ); |
253 |
|
assert( A11.col() == A21.col() ); |
254 |
|
assert( A22.row() == A21.row() ); |
255 |
|
assert( A22.col() == A12.col() ); |
256 |
|
(*this) = A11; |
257 |
|
this->m = A11.row() + A21.row(); |
258 |
|
this->n = A11.col() + A12.col(); |
259 |
|
}; |
260 |
|
|
261 |
|
bool IsTransposed() { return trans; }; |
262 |
|
|
263 |
|
bool HasTheSameBuffer( Data<T> *target ) { return ( target == buff ); }; |
264 |
|
|
265 |
|
bool HasUniformBlockSize() { return has_uniform_block_size; }; |
266 |
|
|
267 |
|
void CreateLeafMatrixBlocks( size_t mb, size_t nb ) |
268 |
|
{ |
269 |
|
/** only the base view can have leaf r/w blocks */ |
270 |
|
if ( base == this ) |
271 |
|
{ |
272 |
|
if ( !rwblocks.HasBeenSetup() ) |
273 |
|
{ |
274 |
|
this->mb = mb; |
275 |
|
this->nb = nb; |
276 |
|
rwblocks.Setup( |
277 |
|
(size_t)std::ceil( (double)m / mb ), |
278 |
|
(size_t)std::ceil( (double)n / nb ) ); |
279 |
|
} |
280 |
|
assert( this->mb == mb ); |
281 |
|
assert( this->nb == nb ); |
282 |
|
} |
283 |
|
else |
284 |
|
{ |
285 |
|
base->CreateLeafMatrixBlocks( mb, nb ); |
286 |
|
} |
287 |
|
}; |
288 |
|
|
289 |
|
size_t GetRowBlockSize() |
290 |
|
{ |
291 |
|
if ( base == this ) return mb; |
292 |
|
else return base->GetRowBlockSize(); |
293 |
|
}; |
294 |
|
|
295 |
|
size_t GetColumnBlockSize() |
296 |
|
{ |
297 |
|
if ( base == this ) return nb; |
298 |
|
else return base->GetColumnBlockSize(); |
299 |
|
}; |
300 |
|
|
301 |
|
bool HasLeafReadWriteBlocks() |
302 |
|
{ |
303 |
|
if ( base == this ) return rwblocks.HasBeenSetup(); |
304 |
|
else return base->HasLeafReadWriteBlocks(); |
305 |
|
}; |
306 |
|
|
307 |
|
/** |
308 |
|
* @brief If leaf r/w blocks were created, then the r/w dependency |
309 |
|
* applies to all leaf r/w blocks covered by this view. |
310 |
|
* Otherwise, the r/w dependency only applies to this view. |
311 |
|
*/ |
312 |
|
void DependencyAnalysis( ReadWriteType type, Task *task ) |
313 |
|
{ |
314 |
|
if ( HasLeafReadWriteBlocks() ) |
315 |
|
{ |
316 |
|
for ( size_t j = 0; j < n; j += GetColumnBlockSize() ) |
317 |
|
for ( size_t i = 0; i < m; i += GetRowBlockSize() ) |
318 |
|
DependencyAnalysis( offm + i, offn + j, type, task ); |
319 |
|
} |
320 |
|
else |
321 |
|
{ |
322 |
|
ReadWrite::DependencyAnalysis( type, task ); |
323 |
|
} |
324 |
|
}; |
325 |
|
|
326 |
|
void DependencyAnalysis( size_t i, size_t j, ReadWriteType type, Task *task ) |
327 |
|
{ |
328 |
|
if ( base == this ) |
329 |
|
{ |
330 |
|
rwblocks.DependencyAnalysis( i / mb, j / nb, type, task ); |
331 |
|
} |
332 |
|
else |
333 |
|
{ |
334 |
|
base->DependencyAnalysis( i, j, type, task ); |
335 |
|
} |
336 |
|
}; |
337 |
|
|
338 |
|
void DependencyCleanUp() |
339 |
|
{ |
340 |
|
if ( base == this ) rwblocks.DependencyCleanUp(); |
341 |
|
else base->DependencyCleanUp(); |
342 |
|
}; |
343 |
|
|
344 |
|
/** return the row size of the current view */ |
345 |
|
size_t row() { return m; }; |
346 |
|
|
347 |
|
/** return the col size of the current view */ |
348 |
|
size_t col() { return n; }; |
349 |
|
|
350 |
|
/** return leading dimension of the buffer */ |
351 |
|
size_t ld() { return buff->row(); }; |
352 |
|
|
353 |
|
/** return the pointer of the current view in the buffer */ |
354 |
|
T *data() |
355 |
|
{ |
356 |
|
assert( buff ); |
357 |
|
size_t offset; |
358 |
|
if ( trans ) offset = offm * ld() + offn; |
359 |
|
else offset = offn * ld() + offm; |
360 |
|
return ( buff->data() + offset ); |
361 |
|
}; |
362 |
|
|
363 |
|
/** print out all information */ |
364 |
|
void Print() |
365 |
|
{ |
366 |
|
if ( trans ) |
367 |
|
{ |
368 |
|
printf( "[ %5lu+%5lu:%5lu ][ %5lu+%5lu:%5lu ]\n", |
369 |
|
offm, m, buff->col(), offn, n, buff->row() ); |
370 |
|
} |
371 |
|
else |
372 |
|
{ |
373 |
|
printf( "[ %5lu+%5lu:%5lu ][ %5lu+%5lu:%5lu ]\n", |
374 |
|
offm, m, buff->row(), offn, n, buff->col() ); |
375 |
|
} |
376 |
|
}; |
377 |
|
|
378 |
|
private: |
379 |
|
|
380 |
|
/** whether this is a transpose view? */ |
381 |
|
bool trans = false; |
382 |
|
|
383 |
|
size_t m = 0; |
384 |
|
|
385 |
|
size_t n = 0; |
386 |
|
|
387 |
|
size_t offm = 0; |
388 |
|
|
389 |
|
size_t offn = 0; |
390 |
|
|
391 |
|
View<T> *base = NULL; |
392 |
|
|
393 |
|
Data<T> *buff = NULL; |
394 |
|
|
395 |
|
/** we can only have one kind of mb and nb */ |
396 |
|
size_t mb = 0; |
397 |
|
|
398 |
|
size_t nb = 0; |
399 |
|
|
400 |
|
bool has_uniform_block_size = true; |
401 |
|
|
402 |
|
MatrixReadWrite rwblocks; |
403 |
|
|
404 |
|
}; /** end class View */ |
405 |
|
|
406 |
|
|
407 |
|
/** |
408 |
|
* @brief |
409 |
|
*/ |
410 |
|
template<typename T> |
411 |
|
void Partition1x2 |
412 |
|
( |
413 |
|
View<T> &A, View<T> &A1, View<T> &A2, |
414 |
|
size_t nb, SideType side |
415 |
|
) |
416 |
|
{ |
417 |
|
A.Partition1x2( A1, A2, nb, side ); |
418 |
|
}; /** end Partition1x2() */ |
419 |
|
|
420 |
|
|
421 |
|
/** |
422 |
|
* @brief |
423 |
|
*/ |
424 |
|
template<typename T> |
425 |
|
void Partition2x1 |
426 |
|
( |
427 |
|
View<T> &A, View<T> &A1, |
428 |
|
View<T> &A2, |
429 |
|
size_t mb, SideType side |
430 |
|
) |
431 |
|
{ |
432 |
|
A.Partition2x1( A1, |
433 |
|
A2, mb, side ); |
434 |
|
}; /** end Partition2x1() */ |
435 |
|
|
436 |
|
|
437 |
|
/** |
438 |
|
* @brief |
439 |
|
*/ |
440 |
|
template<typename T> |
441 |
|
void Partition2x2 |
442 |
|
( |
443 |
|
View<T> &A, View<T> &A11, View<T> &A12, |
444 |
|
View<T> &A21, View<T> &A22, |
445 |
|
size_t mb, size_t nb, QuadrantType quadrant |
446 |
|
) |
447 |
|
{ |
448 |
|
A.Partition2x2( A11, A12, |
449 |
|
A21, A22, mb, nb, quadrant ); |
450 |
|
}; /** end Partition2x2() */ |
451 |
|
|
452 |
|
|
453 |
|
/** |
454 |
|
* @brief |
455 |
|
*/ |
456 |
|
template<typename T> |
457 |
|
void Repartition1x2To1x3 |
458 |
|
( |
459 |
|
View<T> &AL, View<T> &AR, |
460 |
|
View<T> &A0, View<T> &A1, View<T> &A2, |
461 |
|
size_t nb, SideType side |
462 |
|
) |
463 |
|
{ |
464 |
|
switch ( side ) |
465 |
|
{ |
466 |
|
case LEFT: |
467 |
|
{ |
468 |
|
AL.Partition1x2( A0, A1, nb, RIGHT ); |
469 |
|
A2 = AR; |
470 |
|
break; |
471 |
|
} |
472 |
|
case RIGHT: |
473 |
|
{ |
474 |
|
A0 = AL; |
475 |
|
AR.Partition1x2( A1, A2, nb, LEFT ); |
476 |
|
break; |
477 |
|
} |
478 |
|
default: |
479 |
|
{ |
480 |
|
printf( "invalid side\n" ); |
481 |
|
break; |
482 |
|
} |
483 |
|
} |
484 |
|
|
485 |
|
}; /** end Repartition1x2To1x3()*/ |
486 |
|
|
487 |
|
|
488 |
|
template<typename T> |
489 |
|
void ContinueWith1x3To1x2 |
490 |
|
( |
491 |
|
View<T> &AL, View<T> &AR, |
492 |
|
View<T> &A0, View<T> &A1, View<T> &A2, |
493 |
|
SideType side |
494 |
|
) |
495 |
|
{ |
496 |
|
switch ( side ) |
497 |
|
{ |
498 |
|
case LEFT: |
499 |
|
{ |
500 |
|
AL.ContinueWith1x2( A0, A1 ); |
501 |
|
AR = A2; |
502 |
|
break; |
503 |
|
} |
504 |
|
case RIGHT: |
505 |
|
{ |
506 |
|
AL = A0; |
507 |
|
AR.ContinueWith1x2( A1, A2 ); |
508 |
|
break; |
509 |
|
} |
510 |
|
default: |
511 |
|
{ |
512 |
|
printf( "invalid side\n" ); |
513 |
|
break; |
514 |
|
} |
515 |
|
} |
516 |
|
}; /** end ContinueWith1x3To1x2() */ |
517 |
|
|
518 |
|
|
519 |
|
|
520 |
|
|
521 |
|
template<typename T> |
522 |
|
void Repartition2x1To3x1 |
523 |
|
( |
524 |
|
View<T> &AT, View<T> &A0, |
525 |
|
View<T> &A1, |
526 |
|
View<T> &AB, View<T> &A2, |
527 |
|
size_t mb, SideType side |
528 |
|
) |
529 |
|
{ |
530 |
|
switch ( side ) |
531 |
|
{ |
532 |
|
case TOP: |
533 |
|
{ |
534 |
|
AT.Partition2x1( A0, |
535 |
|
A1, mb, BOTTOM ); |
536 |
|
A2 = AB; |
537 |
|
break; |
538 |
|
} |
539 |
|
case BOTTOM: |
540 |
|
{ |
541 |
|
A0 = AT; |
542 |
|
AB.Partition2x1( A1, |
543 |
|
A2, mb, TOP ); |
544 |
|
break; |
545 |
|
} |
546 |
|
default: |
547 |
|
{ |
548 |
|
printf( "invalid side\n" ); |
549 |
|
break; |
550 |
|
} |
551 |
|
} |
552 |
|
}; /** end Repartition2x1To3x1()*/ |
553 |
|
|
554 |
|
|
555 |
|
template<typename T> |
556 |
|
void ContinueWith3x1To2x1 |
557 |
|
( |
558 |
|
View<T> &AT, View<T> &A0, |
559 |
|
View<T> &A1, |
560 |
|
View<T> &AB, View<T> &A2, |
561 |
|
SideType side |
562 |
|
) |
563 |
|
{ |
564 |
|
switch ( side ) |
565 |
|
{ |
566 |
|
case TOP: |
567 |
|
{ |
568 |
|
AT.ContinueWith2x1( A0, |
569 |
|
A1 ); |
570 |
|
AB = A2; |
571 |
|
break; |
572 |
|
} |
573 |
|
case BOTTOM: |
574 |
|
{ |
575 |
|
AT = A0; |
576 |
|
AB.ContinueWith2x1( A1, |
577 |
|
A2 ); |
578 |
|
break; |
579 |
|
} |
580 |
|
default: |
581 |
|
{ |
582 |
|
printf( "invalid side\n" ); |
583 |
|
break; |
584 |
|
} |
585 |
|
} |
586 |
|
}; /** end ContinueWith3x1To2x1() */ |
587 |
|
|
588 |
|
|
589 |
|
/** |
590 |
|
* @brief |
591 |
|
*/ |
592 |
|
template<typename T> |
593 |
|
void Repartition2x2To3x3 |
594 |
|
( |
595 |
|
View<T> &ATL, View<T> &ATR, View<T> &A00, View<T> &A01, View<T> &A02, |
596 |
|
View<T> &A10, View<T> &A11, View<T> &A12, |
597 |
|
View<T> &ABL, View<T> &ABR, View<T> &A20, View<T> &A21, View<T> &A22, |
598 |
|
size_t mb, size_t nb, QuadrantType quadrant |
599 |
|
) |
600 |
|
{ |
601 |
|
switch ( quadrant ) |
602 |
|
{ |
603 |
|
case TOPLEFT: |
604 |
|
{ |
605 |
|
ATL.Partition2x2( A00, A01, |
606 |
|
A10, A11, mb, nb, BOTTOMRIGHT ); |
607 |
|
ATR.Partition2x1( A02, |
608 |
|
A12, mb, BOTTOM ); |
609 |
|
ABL.Partition1x2( A20, A21, nb, RIGHT ); |
610 |
|
A22 = ABR; |
611 |
|
break; |
612 |
|
} |
613 |
|
case TOPRIGHT: |
614 |
|
{ |
615 |
|
ATL.Partition2x1( A00, |
616 |
|
A10, mb, BOTTOM ); |
617 |
|
ATR.Partition2x2( A01, A02, |
618 |
|
A11, A12, mb, nb, BOTTOMLEFT ); |
619 |
|
A20 = ABL; |
620 |
|
ABR.Partition1x2( A21, A22, nb, LEFT ); |
621 |
|
break; |
622 |
|
} |
623 |
|
case BOTTOMLEFT: |
624 |
|
{ |
625 |
|
ATL.Partition1x2( A00, A01, nb, RIGHT ); |
626 |
|
A02 = ATR; |
627 |
|
ABL.Partition2x2( A10, A11, |
628 |
|
A20, A21, mb, nb, TOPRIGHT ); |
629 |
|
ABR.Partition2x1( A12, |
630 |
|
A22, mb, TOP ); |
631 |
|
break; |
632 |
|
} |
633 |
|
case BOTTOMRIGHT: |
634 |
|
{ |
635 |
|
A00 = ATL; |
636 |
|
ATR.Partition1x2( A01, A02, nb, LEFT ); |
637 |
|
ABL.Partition2x1( A10, |
638 |
|
A20, mb, TOP ); |
639 |
|
ABR.Partition2x2( A11, A12, |
640 |
|
A21, A22, mb, nb, TOPLEFT ); |
641 |
|
break; |
642 |
|
} |
643 |
|
default: |
644 |
|
{ |
645 |
|
printf( "invalid quadrant\n" ); |
646 |
|
break; |
647 |
|
} |
648 |
|
} |
649 |
|
}; /** end Repartition2x2To3x3() */ |
650 |
|
|
651 |
|
|
652 |
|
|
653 |
|
/** |
654 |
|
* @brief |
655 |
|
*/ |
656 |
|
template<typename T> |
657 |
|
void ContinueWith3x3To2x2 |
658 |
|
( |
659 |
|
View<T> &ATL, View<T> &ATR, View<T> &A00, View<T> &A01, View<T> &A02, |
660 |
|
View<T> &A10, View<T> &A11, View<T> &A12, |
661 |
|
View<T> &ABL, View<T> &ABR, View<T> &A20, View<T> &A21, View<T> &A22, |
662 |
|
QuadrantType quadrant |
663 |
|
) |
664 |
|
{ |
665 |
|
switch ( quadrant ) |
666 |
|
{ |
667 |
|
case TOPLEFT: |
668 |
|
{ |
669 |
|
ATL.ContinueWith2x2( A00, A01, |
670 |
|
A10, A11 ); |
671 |
|
ATR.ContinueWith2x1( A02, |
672 |
|
A12 ); |
673 |
|
ABL.ContinueWith1x2( A20, A21 ); |
674 |
|
ABR = A22; |
675 |
|
break; |
676 |
|
} |
677 |
|
case TOPRIGHT: |
678 |
|
{ |
679 |
|
ATL.ContinueWith2x1( A00, |
680 |
|
A10 ); |
681 |
|
ATR.ContinueWith2x2( A01, A02, |
682 |
|
A11, A12 ); |
683 |
|
ABL = A20; |
684 |
|
ABR.ContinueWith1x2( A21, A22 ); |
685 |
|
break; |
686 |
|
} |
687 |
|
case BOTTOMLEFT: |
688 |
|
{ |
689 |
|
ATL.ContinueWith1x2( A00, A01 ); |
690 |
|
ATR = A02; |
691 |
|
ABL.ContinueWith2x2( A10, A11, |
692 |
|
A20, A21 ); |
693 |
|
ABR.ContinueWith2x1( A12, |
694 |
|
A22 ); |
695 |
|
break; |
696 |
|
} |
697 |
|
case BOTTOMRIGHT: |
698 |
|
{ |
699 |
|
ATL = A00; |
700 |
|
ATR.ContinueWith1x2( A01, A02 ); |
701 |
|
ABL.ContinueWith2x1( A10, |
702 |
|
A20 ); |
703 |
|
ABR.ContinueWith2x2( A11, A12, |
704 |
|
A21, A22 ); |
705 |
|
break; |
706 |
|
} |
707 |
|
default: |
708 |
|
{ |
709 |
|
printf( "invalid quadrant\n" ); |
710 |
|
break; |
711 |
|
} |
712 |
|
} |
713 |
|
}; /** end ContinueWith3x3To2x2() */ |
714 |
|
|
715 |
|
|
716 |
|
|
717 |
|
}; /** end namespace hmlp */ |
718 |
|
|
719 |
|
#endif /** define VIEW_HPP */ |