00001
00030 #ifndef _TENSORARRAY_H
00031 #define _TENSORARRAY_H
00032
00033
00034 #include <vector>
00035 #include <cstdarg>
00036 #include <iterator>
00037
00038 #include <TensorArrayRowIterator.H>
00039 #include <TensorArrayIndexIterator.H>
00040 #include <TensorArraySliceIterator.H>
00041 #include <arglst.H>
00042 #include <xmath.H>
00043 #include <ListAssignment.H>
00044 #include <tensor_array_typedef.H>
00045 #include <Transform.H>
00046
00047 using namespace std;
00048
00049 namespace xchen
00050 {
00051
00052
00053
00057 template<typename T, int dims>
00058 class TensorArray
00059 {
00060 def_type_name_for_tensor_array(T, dims);
00061
00062 friend class TensorArray<T,dims-1>;
00063
00064 public:
00065 TensorArray();
00066 explicit TensorArray(int sz, ...);
00067 explicit TensorArray(int* sz);
00068 TensorArray(MyType const&);
00069 TensorArray(MyType const&, int d, int s, int e);
00070 TensorArray(MyType const&, int*start, int*end);
00071
00072 TensorArray(TensorArray<T,dims+1> const& rhs, int d, int s);
00073
00074
00075 ~TensorArray() { delete [] data; delete idx_itr; }
00076
00077 TensorArray& Transform(xchen::Transform const&);
00078
00079 void Clear();
00080 bool Empty() const { return find(sz, sz+dims, 0) != sz+dims; }
00081
00082 void PopFront(int i=0);
00083 void PopBack(int i=0);
00084
00085 void Insert(linear_iterator itr, T const& val);
00086 void Insert(int dir, int before);
00087
00088 void SetN(int N);
00089
00090 void InsertMiddlePoints(bool average=true);
00091
00092 void Averaging();
00093
00094 TensorArray& operator=(const TensorArray& rhs);
00095
00096 int GetSize(int dir=0) const { return sz[dir]; }
00097 void GetSize(int* Sz) const { copy(sz, sz+dims, Sz); }
00098 int GetTotalSize() const { return totalSz; }
00099
00100 void Reserve(int newCapacity,...);
00101 void Reserve(int* newCapacity);
00102 void Resize(int newSz, ...);
00103 void Resize(int* newSz);
00104 void ResizeOneDirection(int i, int new_sz);
00105 void CopyExtend(int left, ...);
00106 void CopyExtend(int* rightleft);
00107 void CopyExtendAtDirection(int i,
00108 int left, int right);
00109 void ExtendAtDirection(int i,
00110 int left, int right);
00111 void Extend(int left, ...);
00112 void Extend(int* rightleft);
00113
00114 slc_iterator SliceIterate(int dir=0, int start=0, int end=0) { return slc_iterator(this, dir, start, end); }
00115
00116 linear_iterator LinearIterate(int dir, int start, int len);
00117 linear_iterator LinearIterate(int*start=0, int*end=0) { return linear_iterator(this, start, end); }
00118 linear_iterator Begin() { return LinearIterate().Begin(); }
00119 linear_iterator End() { return LinearIterate().End(); }
00120
00121 linear_riterator LinearReverseIterate(int dir, int start, int len);
00122 linear_riterator LinearReverseIterate(int*start=0, int*end=0) { return linear_riterator(this, start, end); }
00123 linear_riterator Rbegin() { return LinearReverseIterate().Begin(); }
00124 linear_riterator Rend() { return LinearReverseIterate().End(); }
00125
00126 row_iterator RowIterate(int row_d,int subarray_d,int start,int len);
00127 row_iterator RowIterate(int d=0, int* start = 0, int* end=0) { return row_iterator(d, this, start, end); }
00128 row_riterator RowReverseIterate(int r_d,int sub_d,int start,int L);
00129 row_riterator RowReverseIterate(int d=0, int* start=0, int* end=0) { return row_riterator(d, this, start, end); }
00130
00131 idx_op_ret_t operator[](int i);
00132 T& operator[](Vector<int,dims>const &i);
00133 ListAssignmentCheckSzRt<T,linear_iterator> operator=(T);
00134
00135 T const& GetElement(int* idx) const;
00136 T const& GetElement(int i, ...) const;
00137
00138 friend ostream& operator<< <>(ostream& os, const TensorArray&);
00139 void PrintShape() const;
00140
00141 private:
00142 T* data;
00143 int sz[dims], totalSz;
00144 int capacity[dims];
00145 int n;
00146 int stride[dims+1];
00147 idx_itr_t* idx_itr;
00148
00149 private:
00150 void compute_stride_totalSz();
00151 void allocate() { delete [] data; data = stride[dims]? new T[stride[dims]] : 0; }
00152 void new_idx_itr() { delete idx_itr; idx_itr = new idx_itr_t(stride, sz); }
00153
00154 void reset_after_resize();
00155 void init_after_resize();
00156 void init_after_reshape();
00157
00158 void initElements(const TensorArray& rhs);
00159
00160 bool generate_even_idx_in_i_plus_dimension(int i=-1, int* start=0);
00161 bool generate_idx_of_boundary_element(int* idx=0, int*s=0,int*e=0);
00162 void copy_extend(int* idx, int* start, int* end);
00163 void extend(bool cpy, int* leftright);
00164 };
00165
00166
00167
00168
00169 template<typename T>
00170 class TensorArray<T,0>
00171 {
00172 public:
00173 TensorArray(TensorArray<T,1> const&, int, int) { }
00174 friend ostream& operator<< (ostream& os, const TensorArray&) { return os; }
00175 };
00176
00177 struct IdxRange
00178 {
00179 IdxRange(int _d, int _s, int _e) : d(_d), s(_s), e(_e) { }
00180 int d, s, e;
00181 };
00182
00183
00184
00185 template<typename T, int dims>
00186 inline TensorArray<T,dims> :: TensorArray() : data(0), n(0), idx_itr(0)
00187 {
00188 bzero(sz, sizeof(int) * dims);
00189 bzero(capacity, sizeof(int) * dims);
00190 compute_stride_totalSz();
00191 }
00192 template<typename T, int dims>
00193 inline TensorArray<T,dims> :: TensorArray(int arg1, ...) : data(0), n(0), idx_itr(0)
00194 {
00195 get_reverse_ints_va(sz, dims);
00196 init_after_resize();
00197 }
00198
00199 template<typename T, int dims>
00200 inline TensorArray<T,dims> :: TensorArray(int* Sz) : data(0), n(0), idx_itr(0)
00201 {
00202 copy(Sz, Sz+dims, sz);
00203 init_after_resize();
00204 }
00205 template<typename T, int dims>
00206 inline TensorArray<T,dims> :: TensorArray(MyType const& rhs) : data(0), n(0), idx_itr(0)
00207 {
00208 copy(&rhs.sz[0], &rhs.sz[0]+dims, sz);
00209 copy(&rhs.capacity[0], &rhs.capacity[0]+dims, capacity);
00210 init_after_reshape();
00211
00212 TensorArray& _rhs = (TensorArray&) rhs;
00213 std::copy(_rhs.Begin(), _rhs.End(), Begin());
00214 }
00215
00216 template<typename T, int dims>
00217 inline TensorArray<T,dims> :: TensorArray(MyType const& rhs, int d, int s, int e) : data(0), n(0), idx_itr(0)
00218 {
00219 copy(&rhs.sz[0], &rhs.sz[0]+dims, sz);
00220 sz[d] = e - s;
00221
00222 init_after_resize();
00223
00224 TensorArray& _rhs = (TensorArray&)rhs;
00225 linear_iterator itr = _rhs.LinearIterate(d, s, e);
00226 std::copy(itr.Begin(), itr.End(), Begin());
00227 }
00228
00229
00230 template<typename T, int dims>
00231 inline TensorArray<T,dims> :: TensorArray(TensorArray<T,dims+1> const& rhs, int d, int s) : data(0), n(0), idx_itr(0)
00232 {
00233 copy(&rhs.sz[0], &rhs.sz[0]+d, sz);
00234 copy(&rhs.sz[0]+d+1, &rhs.sz[0]+dims+1, sz);
00235
00236 init_after_resize();
00237
00238 SuperType& _rhs = (SuperType&)rhs;
00239 typename SuperType::linear_iterator itr = _rhs.LinearIterate(d, s, 1);
00240 std::copy(itr.Begin(), itr.End(), Begin());
00241 }
00242
00243
00244 template<typename T, int dims>
00245 inline TensorArray<T,dims> :: TensorArray(MyType const& rhs, int* s, int* e) : data(0), n(0), idx_itr(0)
00246 {
00247 transform(s, s+dims, e, sz, minus<int>());
00248
00249 init_after_resize();
00250
00251 TensorArray& _rhs = (TensorArray&)rhs;
00252 linear_iterator itr = _rhs.LinearIterate(s, e);
00253 std::copy(itr.Begin(), itr.End(), Begin());
00254 }
00255
00256
00257 template<typename T, int dims>
00258 inline TensorArray<T,dims>& TensorArray<T,dims>::Transform(xchen::Transform const& trans)
00259 {
00260 for(linear_iterator itr = Begin(); itr!=End(); ++itr)
00261 {
00262 *itr = trans(*itr);
00263 }
00264 return *this;
00265 }
00266
00267
00268
00269 template<typename T, int dims>
00270 inline void TensorArray<T,dims> :: Clear()
00271 {
00272 delete [] data; delete idx_itr;
00273
00274 data = 0; idx_itr = 0; n = 0;
00275
00276 bzero(sz, sizeof(int) * dims);
00277 bzero(capacity, sizeof(int) * dims);
00278 compute_stride_totalSz();
00279 }
00280
00281 template<typename T, int dims>
00282 TensorArray<T,dims>& TensorArray<T,dims> :: operator=(const TensorArray& rhs)
00283 {
00284 if(this != &rhs)
00285 {
00286 copy(&rhs.sz[0], &rhs.sz[0]+dims, sz);
00287
00288 reset_after_resize();
00289
00290 TensorArray& _rhs = (TensorArray&)rhs;
00291 std::copy(_rhs.Begin(), _rhs.End(), Begin());
00292 }
00293 return *this;
00294 }
00295
00296
00297 template<typename T, int dims>
00298 ListAssignmentCheckSzRt<T, typename TensorArray<T,dims> :: linear_iterator> TensorArray<T,dims> :: operator=(T x)
00299 {
00300 data[0] = x;
00301 return ListAssignmentCheckSzRt<T, linear_iterator>(Begin()+1, totalSz-1);
00302 }
00303
00304 template<typename T, int dims>
00305 void TensorArray<T,dims> :: initElements(const TensorArray& rhs)
00306 {
00307 if(this != &rhs)
00308 {
00309 int end[dims];
00310 for(int i=0; i<dims; i++)
00311 end[i] = std::min(sz[i], rhs.sz[i]);
00312
00313 linear_iterator itr1 = ((TensorArray&)rhs).LinearIterate(0, end);
00314 linear_iterator itr2 = LinearIterate(0, end);
00315 std::copy(itr1.Begin(), itr1.End(), itr2.Begin());
00316 }
00317 }
00318
00319
00320 template<typename T, int dims>
00321 inline void TensorArray<T,dims> :: Reserve(int arg1, ...)
00322 {
00323 int new_cap[dims];
00324 get_reverse_ints_va(new_cap, dims);
00325 Reserve(new_cap);
00326 }
00327 template<typename T, int dims>
00328 void TensorArray<T,dims> :: Reserve(int* _new_cap)
00329 {
00330 bool need_alloc = false;
00331 int new_cap[dims];
00332 copy(_new_cap, _new_cap+dims, new_cap);
00333
00334 for(int i=0; i<dims; i++)
00335 {
00336 if(capacity[i] < new_cap[i])
00337 need_alloc = true;
00338 else
00339 new_cap[i] = capacity[i];
00340 }
00341
00342 if(need_alloc)
00343 {
00344 TensorArray<T,dims> old_ar(*this);
00345
00346 copy(new_cap, new_cap+dims, capacity);
00347 init_after_reshape();
00348
00349 copy(old_ar.Begin(), old_ar.End(), Begin());
00350 }
00351 }
00352
00353 template<typename T, int dims>
00354 inline void TensorArray<T,dims> :: reset_after_resize()
00355 {
00356 for(int i=0; i<dims; i++)
00357 if(capacity[i] < sz[i])
00358 capacity[i] = sz[i];
00359
00360 int old_total_memsz = stride[dims];
00361 compute_stride_totalSz();
00362 new_idx_itr();
00363
00364 if( !data || old_total_memsz < stride[dims] )
00365 allocate();
00366 }
00367 template<typename T, int dims>
00368 inline void TensorArray<T,dims> :: init_after_resize()
00369 {
00370 copy(sz, sz+dims, capacity);
00371 compute_stride_totalSz();
00372 new_idx_itr();
00373 allocate();
00374 }
00375
00376 template<typename T, int dims>
00377 inline void TensorArray<T,dims> :: init_after_reshape()
00378 {
00379 compute_stride_totalSz();
00380 new_idx_itr();
00381 allocate();
00382 }
00383
00384
00385 template<typename T, int dims>
00386 inline void TensorArray<T,dims> :: Resize(int arg1, ...)
00387 {
00388 int new_sz[dims];
00389 get_reverse_ints_va(new_sz, dims);
00390 Resize(new_sz);
00391 }
00392 template<typename T, int dims>
00393 void TensorArray<T,dims> :: Resize(int* new_sz)
00394 {
00395 TensorArray<T,dims>* old_ar = data? new TensorArray<T,dims>(*this) : 0;
00396
00397 copy(new_sz, new_sz+dims, sz);
00398 init_after_resize();
00399
00400 if(old_ar)
00401 {
00402 initElements(*old_ar);
00403 delete old_ar;
00404 }
00405
00406 }
00407
00408 template<typename T, int dims>
00409 void TensorArray<T,dims> :: ResizeOneDirection(int i, int new_sz)
00410 {
00411 if(new_sz == sz[i])
00412 return;
00413
00414 TensorArray<T,dims>* old_ar = data? new TensorArray<T,dims>(*this) : 0;
00415
00416 bool need_alloc = false;
00417 int less_sz[dims];
00418 GetSize(less_sz);
00419
00420 if(new_sz < sz[i])
00421 less_sz[i] = new_sz;
00422 else
00423 {
00424 if(new_sz > capacity[i])
00425 {
00426 capacity[i] = new_sz;
00427 need_alloc = true;
00428 }
00429 }
00430 sz[i] = new_sz;
00431
00432 compute_stride_totalSz();
00433 new_idx_itr();
00434
00435 if(need_alloc)
00436 allocate();
00437
00438 if(old_ar)
00439 {
00440 linear_iterator new_itr = LinearIterate(0, less_sz);
00441 linear_iterator old_itr = old_ar->LinearIterate(0, less_sz);
00442 std::copy(old_itr.Begin(), old_itr.End(), new_itr.Begin());
00443 delete old_ar;
00444 }
00445
00446 }
00447
00448 template<typename T, int dims>
00449 void TensorArray<T,dims> :: Insert(linear_iterator itr, T const& val)
00450 {
00451 T* cpy = new T[totalSz];
00452 T *bgn = cpy, *inst, *end = cpy+totalSz;
00453
00454 linear_iterator it = Begin();
00455 for(; it != itr; ++it, ++cpy) *cpy = *it;
00456
00457 inst = cpy;
00458
00459 for(; it != End(); ++it, ++cpy) *cpy = *it;
00460
00461 ResizeOneDirection(dims-1, sz[dims-1]+1);
00462
00463 cpy = bgn;
00464
00465 for(it = Begin(); bgn != inst; ++bgn, ++it) *it = *bgn;
00466
00467 *it = val; ++it;
00468
00469 for(; bgn != end; ++bgn, ++it) *it = *bgn;
00470
00471 delete [] cpy;
00472 }
00473
00474
00475 template<typename T, int dims>
00476 void TensorArray<T,dims> :: Insert(int dir, int before)
00477 {
00478 int len = sz[dir];
00479 TensorArray<T,dims> cpy(*this);
00480 ResizeOneDirection(dir, len+1);
00481 array_copy(dir,before, cpy,0, *this,0);
00482 array_copy(dir,len-before, cpy,before, *this,before+1);
00483 }
00484
00485
00486 template<typename T, int dims>
00487 inline typename TensorArray<T,dims> :: linear_iterator TensorArray<T,dims> :: LinearIterate(int dir, int start_idx, int len)
00488 {
00489 int start[dims], end[dims];
00490 bzero(start, sizeof(int) * dims); GetSize(end);
00491 start[dir] = start_idx, end[dir] = start_idx + len;
00492 return LinearIterate(start, end);
00493 }
00494 template<typename T, int dims>
00495 inline typename TensorArray<T,dims> :: linear_riterator TensorArray<T,dims> :: LinearReverseIterate(int dir, int start_idx, int len)
00496 {
00497 int start[dims], end[dims];
00498 bzero(start, sizeof(int) * dims); GetSize(end);
00499 start[dir] = start_idx, end[dir] = start_idx + len;
00500 return LinearReverseIterate(start, end);
00501 }
00502 template<typename T, int dims>
00503 inline typename TensorArray<T,dims> :: row_iterator TensorArray<T,dims> :: RowIterate(int row_dir, int subarray_dir, int start_idx, int len)
00504 {
00505 int start[dims], end[dims];
00506 bzero(start, sizeof(int) * dims); GetSize(end);
00507 start[subarray_dir] = start_idx, end[subarray_dir] = start_idx + len;
00508 return RowIterate(row_dir, start, end);
00509 }
00510 template<typename T, int dims>
00511 inline typename TensorArray<T,dims> :: row_riterator TensorArray<T,dims> :: RowReverseIterate(int row_dir, int subarray_dir, int start_idx, int len)
00512 {
00513 int start[dims], end[dims];
00514 bzero(start, sizeof(int) * dims); GetSize(end);
00515 start[subarray_dir] = start_idx, end[subarray_dir] = start_idx + len;
00516 return RowReverseIterate(row_dir, start, end);
00517 }
00518
00519
00520 template<typename T, int dims>
00521 void TensorArray<T,dims> :: PopFront(int i)
00522 {
00523 TensorArray<T,dims> cpy(*this);
00524 sz[i]--;
00525 compute_stride_totalSz();
00526 new_idx_itr();
00527
00528 array_copy(i, sz[i], cpy, 1, *this, 0);
00529 }
00530 template<typename T, int dims>
00531 void TensorArray<T,dims> :: PopBack(int i)
00532 {
00533 sz[i]--;
00534 compute_stride_totalSz();
00535 new_idx_itr();
00536 }
00537
00538 template<typename T, int dims>
00539 inline void TensorArray<T,dims> :: Extend(int arg1, ...)
00540 {
00541 int leftright[2*dims];
00542 get_reverse_ints_va(leftright, 2*dims);
00543 Extend(leftright);
00544 }
00545 template<typename T, int dims>
00546 inline void TensorArray<T,dims> :: Extend(int* rightleft)
00547 {
00548 extend(false, rightleft);
00549 }
00550 template<typename T, int dims>
00551 inline void TensorArray<T,dims> :: CopyExtend(int arg1, ...)
00552 {
00553 int rightleft[2*dims];
00554 get_reverse_ints_va(rightleft, 2*dims);
00555 CopyExtend(rightleft);
00556 }
00557 template<typename T, int dims>
00558 inline void TensorArray<T,dims> :: CopyExtend(int* rightleft)
00559 {
00560 extend(true, rightleft);
00561 }
00562 template<typename T, int dims>
00563 inline void TensorArray<T,dims> :: CopyExtendAtDirection(int i, int left, int right)
00564 {
00565 int rightleft[2*dims];
00566 bzero(rightleft, sizeof(int) * dims * 2);
00567 rightleft[2*i] = right, rightleft[2*i+1] = left;
00568 CopyExtend(rightleft);
00569 }
00570 template<typename T, int dims>
00571 inline void TensorArray<T,dims> :: ExtendAtDirection(int i, int left, int right)
00572 {
00573 int rightleft[2*dims];
00574 bzero(rightleft, sizeof(int) * dims * 2);
00575 rightleft[2*i] = right, rightleft[2*i+1] = left;
00576 Extend(rightleft);
00577 }
00578
00579
00580 template<typename T, int dims>
00581 void TensorArray<T,dims> :: extend(bool cpy_extend, int* rightleft)
00582 {
00583 TensorArray<T,dims> cpy(*this);
00584 int newsz[dims];
00585 int start[dims], end[dims];
00586 copy(sz, sz+dims, newsz);
00587 for(int i=0; i<dims; i++)
00588 {
00589 newsz[i] += rightleft[2*i] + rightleft[2*i+1];
00590 start[i] = rightleft[2*i+1];
00591 end[i] = start[i] + sz[i];
00592 }
00593 Resize(newsz);
00594 linear_riterator itr = LinearReverseIterate(start, end);
00595 copy(cpy.Rbegin(), cpy.Rend(), itr.Begin());
00596
00597 if(cpy_extend)
00598 {
00599 int idx[dims];
00600 generate_idx_of_boundary_element(idx, start, end);
00601 do
00602 {
00603 copy_extend(idx, start, end);
00604 } while( generate_idx_of_boundary_element() );
00605 }
00606 }
00607
00608
00609 template<typename T, int dims>
00610 bool TensorArray<T,dims> :: generate_idx_of_boundary_element(int* idx, int* start, int* end)
00611 {
00612 const int at_interior = 0, at_start = 1, at_end = 2;
00613 static int *index, s[dims], e[dims], at[dims], len[dims];
00614
00615 if(idx && start && end)
00616 {
00617 index = idx;
00618 copy(start, start+dims, s);
00619 copy(end, end+dims, e);
00620 transform(e, e+dims, s, len, minus<int>());
00621
00622
00623 for(int i=0; i<dims; i++)
00624 {
00625 if(len[i]>2)
00626 {
00627 at[i] = at_interior; index[i] = s[i] + 1;
00628 }
00629 else
00630 {
00631 at[i] = at_start; index[i] = s[i];
00632 }
00633 }
00634 if(find(at, at+dims, at_start) == at+dims)
00635 {
00636 at[0] = at_start; index[0] = s[0];
00637 }
00638
00639 return true;
00640 }
00641
00642 while(1)
00643 {
00644 int i;
00645 for(i=0; i<dims; i++)
00646 {
00647 if(at[i] == at_interior)
00648 {
00649 if(++index[i] < e[i]-1)
00650 return true;
00651 index[i] = s[i] + 1;
00652 }
00653 }
00654 if(i==dims)
00655 {
00656 for(i=0; i<dims; i++)
00657 {
00658 if(len[i]==1) continue;
00659 ++at[i];
00660 if(at[i] == at_start) { index[i] = s[i]; break; }
00661 else if(at[i] == at_end) { index[i] = e[i]-1; break; }
00662 else
00663 if(len[i]>2) { at[i] = at_interior; index[i] = s[i] + 1; }
00664 else { at[i] = at_start; index[i] = s[i]; }
00665 }
00666 }
00667 return i!=dims;
00668 }
00669 }
00670
00671
00672
00673 template<typename T, int dims>
00674 void TensorArray<T,dims> :: copy_extend(int* idx, int* start, int* end)
00675 {
00676 int s[dims], e[dims];
00677 copy(idx, idx+dims, s);
00678 transform(idx, idx+dims, e, bind2nd(plus<int>(), 1));
00679
00680 bool need_ext = false;
00681 for(int i=0; i<dims; i++)
00682 {
00683 if(start[i] && idx[i] == start[i])
00684 {
00685 s[i] = 0; need_ext = true;
00686 }
00687 if(idx[i] == end[i]-1 && end[i] != sz[i])
00688 {
00689 e[i] = sz[i]; need_ext = true;
00690 }
00691 }
00692
00693 if(need_ext)
00694 {
00695 linear_iterator itr = LinearIterate(s,e);
00696 fill(itr.Begin(), itr.End(), GetElement(idx));
00697 }
00698 }
00699
00700
00701
00702
00703 template<typename T, int dims>
00704 void TensorArray<T,dims> :: InsertMiddlePoints(bool average)
00705 {
00706 if(!n) SetN(1);
00707
00708 assert( find(sz, sz+dims, 1) == sz+dims );
00709
00710 for(int i=0; i<dims; i++)
00711 {
00712 sz[i] = 2*sz[i] - 1;
00713 capacity[i] = 2 * capacity[i];
00714 }
00715 n--;
00716 compute_stride_totalSz();
00717 new_idx_itr();
00718
00719 if(!average) return;
00720
00721 int subStart[dims], subEnd[dims];
00722 for(int i=0; i<dims; i++)
00723 {
00724 subStart[i] = 0;
00725 subEnd[i] = sz[i];
00726 generate_even_idx_in_i_plus_dimension(i, subStart);
00727 while(generate_even_idx_in_i_plus_dimension())
00728 {
00729 for(int j=i+1; j<dims; j++)
00730 subEnd[j] = subStart[j] + 1;
00731
00732 for( row_iterator r_itr = RowIterate(i, subStart, subEnd); !r_itr.PastEnd(); ++r_itr)
00733 {
00734 element_iterator e_itr_left = r_itr.Begin();
00735 element_iterator e_itr_right = r_itr.Begin() + 2;
00736 element_iterator e_itr_middle = r_itr.Begin() + 1;
00737 for(; e_itr_right < r_itr.End(); e_itr_left += 2, e_itr_right += 2, e_itr_middle += 2)
00738 {
00739 *e_itr_middle = (*e_itr_left + *e_itr_right) / 2;
00740 }
00741 }
00742 }
00743 }
00744 }
00745
00746 template<typename T, int dims>
00747 bool TensorArray<T,dims> :: generate_even_idx_in_i_plus_dimension(int ii, int * subStart)
00748 {
00749 static int i, *sub_start;
00750 static bool first = false;
00751
00752 if(subStart)
00753 {
00754 i = ii+1;
00755 sub_start = subStart;
00756 for(int j=i; j<dims; j++)
00757 sub_start[j] = j==i? -2 : 0;
00758 first = true;
00759 return true;
00760 }
00761 else if(i >= dims)
00762 return first? (first=false, true) : false;
00763 else
00764 {
00765 for(int j=i; j<dims; j++)
00766 {
00767 if( (sub_start[j] += 2) < sz[j] )
00768 return true;
00769 else
00770 sub_start[j] = 0;
00771 }
00772
00773 return false;
00774 }
00775 }
00776
00777
00778 template<typename T, int dims>
00779 inline void TensorArray<T,dims> :: SetN(int N)
00780 {
00781 if(n!=N)
00782 {
00783 TensorArray<T,dims> cpy(*this);
00784 n = N;
00785 compute_stride_totalSz();
00786 allocate();
00787 new_idx_itr();
00788
00789 std::copy(cpy.Begin(), cpy.End(), Begin());
00790 }
00791 }
00792
00793
00794 template<typename T, int dims>
00795 void TensorArray<T,dims> :: Averaging()
00796 {
00797 int eles_per_cell = int_pow(2, dims);
00798 linear_iterator itr[eles_per_cell];
00799 int start[dims], len[dims], end[dims];
00800
00801 bzero(start, sizeof(int) * dims);
00802 GetSize(len);
00803 transform(len, len+dims, len, bind2nd(minus<int>(), 1));
00804
00805
00806
00807
00808
00809
00810 for(int i=0; i<eles_per_cell; i++)
00811 {
00812 for(int j = 0; i && !(start[j] = 1 - start[j]) && j<dims; j++);
00813 transform(start, start+dims, len, end, plus<int>());
00814 itr[i] = LinearIterate(start, end);
00815 }
00816
00817
00818 while( !itr[0].PastEnd() )
00819 {
00820 for(int i=1; i<eles_per_cell; i++)
00821 {
00822 *itr[0] += *itr[i];
00823 }
00824 *itr[0] /= eles_per_cell;
00825 for(int i=0; i<eles_per_cell; i++)
00826 ++itr[i];
00827 }
00828 GetSize(len);
00829 transform(len, len+dims, len, bind2nd(minus<int>(), 1));
00830 Resize(len);
00831 }
00832
00833
00834
00835
00836 template<typename T, int dims>
00837 inline void TensorArray<T,dims> :: compute_stride_totalSz()
00838 {
00839 int strd = (1 << n);
00840 stride[0] = strd;
00841 for(int i=1; i<=dims; i++)
00842 stride[i] = stride[i-1] * capacity[i-1] * strd;
00843 totalSz = sz[0];
00844 for(int i=1; i<dims; i++)
00845 totalSz *= sz[i];
00846 }
00847
00848
00849 template<typename T, int dims>
00850 inline T& TensorArray<T,dims> :: operator[](Vector<int,dims>const& idx)
00851 {
00852 T* ptr = data;
00853 for(int i=dims-1; i>=0; i--)
00854 {
00855 ptr += stride[i] * idx[i];
00856 }
00857 return *ptr;
00858 }
00859
00860
00861 template<typename T, int dims>
00862 inline typename TensorArrayIndexOperatorTraits<T,dims>::ReturnType TensorArray<T,dims> :: operator[](int i)
00863 {
00864 assert(i<sz[dims-1]);
00865 if(dims>1)
00866 {
00867 idx_itr->setPtr(data);
00868 return (*idx_itr)[i];
00869 }
00870 return idx_op_ret_t(data[i]);
00871 }
00872
00873 template<typename T, int dims>
00874 T const& TensorArray<T,dims> :: GetElement(int arg1, ...) const
00875 {
00876 int idx[dims];
00877 get_reverse_ints_va(idx, dims);
00878 return GetElement(idx);
00879 }
00880 template<typename T, int dims>
00881 T const& TensorArray<T,dims> :: GetElement(int* idx) const
00882 {
00883 T* ptr = data;
00884 for(int i=0; i<dims; i++)
00885 ptr += idx[i] * stride[i];
00886 return *ptr;
00887 }
00888
00889
00890 template<typename T, int dims>
00891 void TensorArray<T,dims> :: PrintShape() const
00892 {
00893 cout << "\nTensorArray of \nSize:\t\t";
00894 for(int i=dims-1; i>=0; i--) cout << "["<< sz[i] << "]";
00895 cout << "\nCapacity:\t";
00896 for(int i=dims-1; i>=0; i--) cout << "["<< capacity[i] << "]";
00897 cout << "\nReserve space:\t2^" << n << "-1\n";
00898 }
00899
00900
00901 template<typename T, int dims>
00902 ostream& operator<< (ostream& os, const TensorArray<T, dims>& _ar)
00903 {
00904 TensorArray<T, dims>& ar = (TensorArray<T, dims>&) _ar;
00905 if(dims==1)
00906 std::copy(ar.Begin(), ar.End(), ostream_iterator<T>(os, " "));
00907 else
00908 {
00909 for(int start = 0; start < ar.GetSize(dims-1); ++start)
00910 {
00911 TensorArray<T, dims-1> sub_array(ar, dims-1, start);
00912 os << sub_array << endl;
00913 }
00914 }
00915 return os ;
00916 }
00917
00918
00919
00921 template<typename T, int dims1, int dims2>
00922 inline void array_copy(int sub_array_at_this_dir, int len,
00923 TensorArray<T,dims1>const& from, int from_start,
00924 TensorArray<T,dims2>& to, int to_start)
00925 {
00926 int i = sub_array_at_this_dir;
00927 int fromStart[dims1], fromEnd[dims1], toStart[dims2], toEnd[dims2];
00928
00929 bzero(fromStart, sizeof(int) * dims1);
00930 from.GetSize(fromEnd);
00931 fromStart[i] = from_start, fromEnd[i] = from_start + len;
00932
00933 bzero(toStart, sizeof(int) * dims2);
00934 to.GetSize(toEnd);
00935 toStart[i] = to_start; toEnd[i] = to_start + len;
00936
00937 typename TensorArray<T,dims1> :: linear_iterator
00938 from_itr = ( (TensorArray<T,dims1>&)(from) ).LinearIterate(fromStart, fromEnd);
00939
00940 typename TensorArray<T,dims2> :: linear_iterator
00941 to_itr = to.LinearIterate(toStart, toEnd);
00942
00943 copy(from_itr.Begin(), from_itr.End(), to_itr.Begin());
00944 }
00945
00946
00947
00948 template<typename T, int dims>
00949 inline TensorArray<T,dims> operator*(Transform const& trans, TensorArray<T,dims>const& ar)
00950 {
00951 TensorArray<T,dims> ret(ar);
00952 ret.Transform(trans);
00953 return ret;
00954 }
00955
00956
00957
00958 }
00959
00960
00961 #endif