[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]
![]() |
vigra/multi_array.hxx | ![]() |
---|
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2003 by Gunnar Kedenburg */ 00004 /* Cognitive Systems Group, University of Hamburg, Germany */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* ( Version 1.2.0, Aug 07 2003 ) */ 00008 /* You may use, modify, and distribute this software according */ 00009 /* to the terms stated in the LICENSE file included in */ 00010 /* the VIGRA distribution. */ 00011 /* */ 00012 /* The VIGRA Website is */ 00013 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 00014 /* Please direct questions, bug reports, and contributions to */ 00015 /* koethe@informatik.uni-hamburg.de */ 00016 /* */ 00017 /* THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR */ 00018 /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ 00019 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ 00020 /* */ 00021 /************************************************************************/ 00022 00023 00024 #ifndef VIGRA_MULTI_ARRAY_HXX 00025 #define VIGRA_MULTI_ARRAY_HXX 00026 00027 #include <memory> 00028 #include <algorithm> 00029 #include "vigra/accessor.hxx" 00030 #include "vigra/tinyvector.hxx" 00031 #include "vigra/rgbvalue.hxx" 00032 #include "vigra/basicimageview.hxx" 00033 #include "vigra/imageiterator.hxx" 00034 #include "vigra/numerictraits.hxx" 00035 #include "vigra/multi_iterator.hxx" 00036 #include "vigra/metaprogramming.hxx" 00037 00038 namespace vigra 00039 { 00040 00041 namespace detail 00042 { 00043 /********************************************************/ 00044 /* */ 00045 /* defaultStride */ 00046 /* */ 00047 /********************************************************/ 00048 00049 /* generates the stride for a gapless shape. 00050 00051 Namespace: vigra::detail 00052 */ 00053 template <unsigned int N> 00054 TinyVector <int, N> defaultStride (const TinyVector <int, N> &shape) 00055 { 00056 TinyVector <int, N> ret; 00057 ret [0] = 1; 00058 for (unsigned int i = 1; i < N; ++i) 00059 ret [i] = ret [i-1] * shape [i-1]; 00060 return ret; 00061 } 00062 00063 /********************************************************/ 00064 /* */ 00065 /* MaybeStrided */ 00066 /* */ 00067 /********************************************************/ 00068 00069 /* metatag implementing a test for marking MultiArrays that were 00070 indexed at the zero'th dimension as strided, and all others as 00071 unstrided. 00072 00073 <b>\#include</b> 00074 "<a href="multi_array_8hxx-source.html">vigra/multi_array.hxx</a>" 00075 00076 Namespace: vigra::detail 00077 */ 00078 template <unsigned int N> 00079 struct MaybeStrided 00080 { 00081 typedef UnstridedArrayTag type; 00082 }; 00083 00084 template <> 00085 struct MaybeStrided <0> 00086 { 00087 typedef StridedArrayTag type; 00088 }; 00089 00090 /********************************************************/ 00091 /* */ 00092 /* MultiIteratorChooser */ 00093 /* */ 00094 /********************************************************/ 00095 00096 /* metatag implementing a test (by pattern matching) for marking 00097 MultiArrays that were indexed at the zero'th dimension as strided. 00098 00099 <b>\#include</b> 00100 "<a href="multi_array_8hxx-source.html">vigra/multi_array.hxx</a>" 00101 00102 Namespace: vigra::detail 00103 */ 00104 template <class O> 00105 struct MultiIteratorChooser 00106 { 00107 struct Nil {}; 00108 00109 template <unsigned int N, class T, class REFERENCE, class POINTER> 00110 struct Traverser 00111 { 00112 typedef Nil type; 00113 }; 00114 }; 00115 00116 /********************************************************/ 00117 /* */ 00118 /* MultiIteratorChooser <StridedArrayTag> */ 00119 /* */ 00120 /********************************************************/ 00121 00122 /* specialization of the MultiIteratorChooser for strided arrays. 00123 00124 <b>\#include</b> 00125 "<a href="multi_array_8hxx-source.html">vigra/multi_array.hxx</a>" 00126 00127 Namespace: vigra::detail 00128 */ 00129 template <> 00130 struct MultiIteratorChooser <StridedArrayTag> 00131 { 00132 template <unsigned int N, class T, class REFERENCE, class POINTER> 00133 struct Traverser 00134 { 00135 typedef StridedMultiIterator <N, T, REFERENCE, POINTER> type; 00136 }; 00137 }; 00138 00139 /********************************************************/ 00140 /* */ 00141 /* MultiIteratorChooser <UnstridedArrayTag> */ 00142 /* */ 00143 /********************************************************/ 00144 00145 /* specialization of the MultiIteratorChooser for unstrided arrays. 00146 00147 <b>\#include</b> 00148 "<a href="multi_array_8hxx-source.html">vigra/multi_array.hxx</a>" 00149 00150 Namespace: vigra::detail 00151 */ 00152 template <> 00153 struct MultiIteratorChooser <UnstridedArrayTag> 00154 { 00155 template <unsigned int N, class T, class REFERENCE, class POINTER> 00156 struct Traverser 00157 { 00158 typedef MultiIterator <N, T, REFERENCE, POINTER> type; 00159 }; 00160 }; 00161 00162 } // namespace detail 00163 00164 /********************************************************/ 00165 /* */ 00166 /* MultiArrayView */ 00167 /* */ 00168 /********************************************************/ 00169 00170 // forward declaration 00171 template <unsigned int N, class T, class C = UnstridedArrayTag> 00172 class MultiArrayView; 00173 template <unsigned int N, class T, class A = std::allocator<T> > 00174 class MultiArray; 00175 00176 /** \brief Base class for, and view to, \ref vigra::MultiArray. 00177 00178 This class implements the interface of both MultiArray and MultiArrayView. 00179 By default, MultiArrayViews are tagged as unstrided. I necessary, strided arrays are 00180 constructed automatically by calls to a variant of the bind...() function. 00181 00182 <b>\#include</b> 00183 "<a href="multi_array_8hxx-source.html">vigra/multi_array.hxx</a>" 00184 00185 Namespace: vigra 00186 */ 00187 00188 template <unsigned int N, class T, class C> 00189 class MultiArrayView 00190 { 00191 public: 00192 00193 /** the array's actual dimensionality. 00194 This ensures that MultiArrayView can also be used for 00195 scalars (that is, when <tt>N == 0</tt>). Calculated as:<br> 00196 \code 00197 actual_dimension = (N==0) ? 1 : N 00198 \endcode 00199 */ 00200 enum ActualDimension { actual_dimension = (N==0) ? 1 : N }; 00201 00202 /** the array's value type 00203 */ 00204 typedef T value_type; 00205 00206 /** reference type (result of operator[]) 00207 */ 00208 typedef value_type &reference; 00209 00210 /** const reference type (result of operator[] const) 00211 */ 00212 typedef const value_type &const_reference; 00213 00214 /** pointer type 00215 */ 00216 typedef value_type *pointer; 00217 00218 /** const pointer type 00219 */ 00220 typedef const value_type *const_pointer; 00221 00222 /** size type 00223 */ 00224 typedef TinyVector <int, actual_dimension> size_type; 00225 00226 /** difference type (used for offsetting) 00227 */ 00228 typedef TinyVector <int, actual_dimension> difference_type; 00229 00230 /** traverser (MultiIterator) type 00231 */ 00232 typedef typename detail::MultiIteratorChooser < 00233 C>::template Traverser <actual_dimension, T, T &, T *>::type traverser; 00234 00235 /** const traverser (MultiIterator) type 00236 */ 00237 typedef typename detail::MultiIteratorChooser < 00238 C>::template Traverser <actual_dimension, T, T const &, T const *>::type const_traverser; 00239 00240 /** the view type associated with this array. 00241 */ 00242 typedef MultiArrayView <N, T, C> view_type; 00243 00244 /** the matrix type associated with this array. 00245 */ 00246 typedef MultiArray <N, T> matrix_type; 00247 00248 protected: 00249 00250 /** the strides (offset of a sample to the next) for every dimension 00251 are stored here. 00252 */ 00253 difference_type m_stride; 00254 00255 /** the shape of the image pointed to is stored here. 00256 */ 00257 difference_type m_shape; 00258 00259 /** pointer to the image. 00260 */ 00261 pointer m_ptr; 00262 00263 private: 00264 00265 /** traverse an array element-by-element by using a difference_type 00266 * object as access coordinates. 00267 */ 00268 bool inc_navigator (difference_type &nav) 00269 { 00270 // essentially, this is nothing more than incrementing a number 00271 // in radix representation up to a certain limit, the shape. 00272 int carry = 1; 00273 for (unsigned int d = 0; d < actual_dimension; ++d) { 00274 if (nav [d] + carry < m_shape [d]) { 00275 nav [d] += carry; 00276 return true; 00277 } else { 00278 nav [d] = 0; 00279 } 00280 } 00281 return false; 00282 } 00283 00284 public: 00285 00286 /** default constructor: create an empty image of size 0. 00287 */ 00288 MultiArrayView () 00289 : m_shape (0), m_stride (0), m_ptr (0) 00290 {} 00291 00292 00293 /** construct from shape and pointer 00294 */ 00295 MultiArrayView (const difference_type &shape, pointer ptr); 00296 00297 /** construct from shape, strides (offset of a sample to the next) 00298 for every dimension) and pointer 00299 */ 00300 MultiArrayView (const difference_type &shape, 00301 const difference_type &stride, 00302 pointer ptr); 00303 00304 /** array access. 00305 */ 00306 reference operator[] (const difference_type &d) 00307 { 00308 return m_ptr [dot (d, m_stride)]; 00309 } 00310 00311 /** array access. 00312 */ 00313 const_reference operator[] (const difference_type &d) const 00314 { 00315 return m_ptr [dot (d, m_stride)]; 00316 } 00317 00318 /** 1D array access. Use only if N == 1. 00319 */ 00320 reference operator() (int x) 00321 { 00322 return m_ptr [m_stride[0]*x]; 00323 } 00324 00325 /** 2D array access. Use only if N == 2. 00326 */ 00327 reference operator() (int x, int y) 00328 { 00329 return m_ptr [m_stride[0]*x + m_stride[1]*y]; 00330 } 00331 00332 /** 3D array access. Use only if N == 3. 00333 */ 00334 reference operator() (int x, int y, int z) 00335 { 00336 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z]; 00337 } 00338 00339 /** 4D array access. Use only if N == 4. 00340 */ 00341 reference operator() (int x, int y, int z, int u) 00342 { 00343 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u]; 00344 } 00345 00346 /** 5D array access. Use only if N == 5. 00347 */ 00348 reference operator() (int x, int y, int z, int u, int v) 00349 { 00350 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v]; 00351 } 00352 00353 /** 1D const array access. Use only if N == 1. 00354 */ 00355 const_reference operator() (int x) const 00356 { 00357 return m_ptr [m_stride[0]*x]; 00358 } 00359 00360 /** 2D const array access. Use only if N == 2. 00361 */ 00362 const_reference operator() (int x, int y) const 00363 { 00364 return m_ptr [m_stride[0]*x + m_stride[1]*y]; 00365 } 00366 00367 /** 3D const array access. Use only if N == 3. 00368 */ 00369 const_reference operator() (int x, int y, int z) const 00370 { 00371 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z]; 00372 } 00373 00374 /** 4D const array access. Use only if N == 4. 00375 */ 00376 const_reference operator() (int x, int y, int z, int u) const 00377 { 00378 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u]; 00379 } 00380 00381 /** 5D const array access. Use only if N == 5. 00382 */ 00383 const_reference operator() (int x, int y, int z, int u, int v) const 00384 { 00385 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v]; 00386 } 00387 00388 00389 #if 0 00390 /** shape assignment. 00391 */ 00392 template <class CN> 00393 reference operator= (const MultiArrayView <N, T, CN>& rhs) 00394 { 00395 assert (shape () == rhs.shape ()); 00396 difference_type nav; 00397 if (shape () != nav) 00398 (*this) [nav] = rhs [nav]; 00399 while (inc_navigator (nav)) 00400 (*this) [nav] = rhs [nav]; 00401 } 00402 #endif /* #if 0 */ 00403 00404 00405 #ifndef NO_OUT_OF_LINE_MEMBER_TEMPLATES 00406 /** bind the M outmost dimensions to certain indices. 00407 this reduces the dimensionality of the image to 00408 min { 1, N-M } 00409 */ 00410 template <unsigned int M> 00411 MultiArrayView <N-M, T, C> bindOuter (const TinyVector <int, M> &d) const; 00412 00413 /** bind the M innermost dimensions to certain indices. 00414 this reduces the dimensionality of the image to 00415 min { 1, N-M } 00416 */ 00417 template <unsigned int M> 00418 MultiArrayView <N-M, T, StridedArrayTag> 00419 bindInner (const TinyVector <int, M> &d) const; 00420 00421 /** bind dimension M to index d. 00422 this reduces the dimensionality of the image to 00423 min { 1, N-1 } 00424 */ 00425 template <unsigned int M> 00426 MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type > 00427 bind (int d) const; 00428 #else 00429 template <unsigned int M> 00430 MultiArrayView <N-M, T, C> bindOuter (const TinyVector <int, M> &d) const 00431 { 00432 return bindOuterImpl(*this, d); 00433 } 00434 00435 template <unsigned int M> 00436 MultiArrayView <N-M, T, StridedArrayTag> 00437 bindInner (const TinyVector <int, M> &d) const 00438 { 00439 return bindInnerImpl(*this, d); 00440 } 00441 00442 template <unsigned int M> 00443 MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type > 00444 bind (int d) const 00445 { 00446 return bindImpl<M>(*this, d); 00447 } 00448 #endif 00449 00450 /** bind the outmost dimension to a certain index. 00451 this reduces the dimensionality of the image to 00452 min { 1, N-1 } 00453 */ 00454 MultiArrayView <N-1, T, C> bindOuter (int d) const; 00455 00456 /** bind the innermost dimension to a certain index. 00457 this reduces the dimensionality of the image to 00458 min { 1, N-1 } 00459 */ 00460 MultiArrayView <N-1, T, StridedArrayTag> bindInner (int d) const; 00461 00462 /** bind dimension m to index d. 00463 this reduces the dimensionality of the image to 00464 min { 1, N-1 } 00465 */ 00466 MultiArrayView <N-1, T, StridedArrayTag> 00467 bindAt (int m, int d) const; 00468 00469 /** bind dimension m to index d. 00470 this reduces the dimensionality of the image to 00471 min { 1, N-1 } 00472 */ 00473 MultiArrayView <N-1, T, StridedArrayTag> 00474 bindRow (int d) const; 00475 00476 /** bind dimension m to index d. 00477 this reduces the dimensionality of the image to 00478 min { 1, N-1 } 00479 */ 00480 MultiArrayView <N-1, T, C> 00481 bindColumn (int d) const; 00482 00483 /** create a rectangular subarray that spans between the 00484 points p and q, where p is in the subarray, q not. 00485 */ 00486 MultiArrayView subarray (const difference_type &p, 00487 const difference_type &q) const 00488 { 00489 const int offset = dot (m_stride, p); 00490 return MultiArrayView (q - p, m_stride, m_ptr + offset); 00491 } 00492 00493 /** apply an additional striding to the image, thereby reducing 00494 the shape of the array. 00495 for example, multiplying the stride of dimension one by three 00496 turns an appropriately layed out (interleaved) rgb image into 00497 a single band image. 00498 */ 00499 MultiArrayView <N, T, StridedArrayTag> 00500 stridearray (const difference_type &s) const 00501 { 00502 difference_type shape = m_shape; 00503 for (unsigned int i = 0; i < actual_dimension; ++i) 00504 shape [i] /= s [i]; 00505 return MultiArrayView <N, T, StridedArrayTag> 00506 (shape, m_stride * s, m_ptr); 00507 } 00508 00509 /** number of the elements in the array. 00510 */ 00511 std::size_t elementCount () const 00512 { 00513 return m_shape [actual_dimension-1] * m_stride [actual_dimension-1]; 00514 } 00515 00516 /** return the array's size (same as the shape). 00517 */ 00518 const size_type & size () const 00519 { 00520 return m_shape; 00521 } 00522 00523 /** return the array's shape. 00524 */ 00525 const difference_type & shape () const 00526 { 00527 return m_shape; 00528 } 00529 00530 /** return the array's shape at a certain dimension. 00531 */ 00532 int shape (int n) const 00533 { 00534 return m_shape [n]; 00535 } 00536 00537 /** return the array's stride for every dimension. 00538 */ 00539 const difference_type & stride () const 00540 { 00541 return m_stride; 00542 } 00543 00544 /** return the array's stride at a certain dimension. 00545 */ 00546 int stride (int n) const 00547 { 00548 return m_stride [n]; 00549 } 00550 00551 /** return the pointer to the image data 00552 */ 00553 pointer data () const 00554 { 00555 return m_ptr; 00556 } 00557 00558 /** returns the N-dimensional MultiIterator pointing 00559 to the first element in every dimension. 00560 */ 00561 traverser traverser_begin () 00562 { 00563 traverser ret (m_ptr, m_stride.begin (), m_shape.begin ()); 00564 return ret; 00565 } 00566 00567 /** returns the N-dimensional MultiIterator pointing 00568 to the const first element in every dimension. 00569 */ 00570 const_traverser traverser_begin () const 00571 { 00572 const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ()); 00573 return ret; 00574 } 00575 00576 /** returns the N-dimensional MultiIterator pointing 00577 beyond the last element in dimension N, and to the 00578 first element in every other dimension. 00579 */ 00580 traverser traverser_end () 00581 { 00582 traverser ret (m_ptr, m_stride.begin (), m_shape.begin ()); 00583 ret += m_shape [actual_dimension-1]; 00584 return ret; 00585 } 00586 00587 /** returns the N-dimensional const MultiIterator pointing 00588 beyond the last element in dimension N, and to the 00589 first element in every other dimension. 00590 */ 00591 const_traverser traverser_end () const 00592 { 00593 const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ()); 00594 ret += m_shape [actual_dimension-1]; 00595 return ret; 00596 } 00597 00598 view_type view () 00599 { 00600 return *this; 00601 } 00602 }; 00603 00604 template <unsigned int N, class T, class C> 00605 MultiArrayView <N, T, C>::MultiArrayView (const difference_type &shape, 00606 pointer ptr) 00607 : m_shape (shape), m_stride (defaultStride (shape)), m_ptr (ptr) 00608 {} 00609 00610 template <unsigned int N, class T, class C> 00611 MultiArrayView <N, T, C>::MultiArrayView 00612 (const difference_type &shape, const difference_type &stride, pointer ptr) 00613 : m_shape (shape), m_stride (stride), m_ptr (ptr) 00614 {} 00615 00616 #ifndef NO_OUT_OF_LINE_MEMBER_TEMPLATES 00617 template <unsigned int N, class T, class C> 00618 template <unsigned int M> 00619 MultiArrayView <N-M, T, C> 00620 MultiArrayView <N, T, C>::bindOuter (const TinyVector <int, M> &d) const 00621 { 00622 TinyVector <int, M> stride; 00623 stride.init (m_stride.begin () + N-M, m_stride.end ()); 00624 pointer ptr = m_ptr + dot (d, stride); 00625 static const int NNew = (N-M == 0) ? 1 : N-M; 00626 TinyVector <int, NNew> inner_shape, inner_stride; 00627 if (N-M == 0) 00628 { 00629 inner_shape [0] = 1; 00630 inner_stride [0] = 0; 00631 } 00632 else 00633 { 00634 inner_shape.init (m_shape.begin (), m_shape.end () - M); 00635 inner_stride.init (m_stride.begin (), m_stride.end () - M); 00636 } 00637 return MultiArrayView <N-M, T, C> (inner_shape, inner_stride, ptr); 00638 } 00639 00640 template <unsigned int N, class T, class C> 00641 template <unsigned int M> 00642 MultiArrayView <N - M, T, StridedArrayTag> 00643 MultiArrayView <N, T, C>::bindInner (const TinyVector <int, M> &d) const 00644 { 00645 TinyVector <int, M> stride; 00646 stride.init (m_stride.begin (), m_stride.end () - N + M); 00647 pointer ptr = m_ptr + dot (d, stride); 00648 static const int NNew = (N-M == 0) ? 1 : N-M; 00649 TinyVector <int, NNew> outer_shape, outer_stride; 00650 if (N-M == 0) 00651 { 00652 outer_shape [0] = 1; 00653 outer_stride [0] = 0; 00654 } 00655 else 00656 { 00657 outer_shape.init (m_shape.begin () + M, m_shape.end ()); 00658 outer_stride.init (m_stride.begin () + M, m_stride.end ()); 00659 } 00660 return MultiArrayView <N-M, T, StridedArrayTag> 00661 (outer_shape, outer_stride, ptr); 00662 } 00663 00664 template <unsigned int N, class T, class C> 00665 template <unsigned int M> 00666 MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type > 00667 MultiArrayView <N, T, C>::bind (int d) const 00668 { 00669 static const int NNew = (N-1 == 0) ? 1 : N-1; 00670 TinyVector <int, NNew> shape, stride; 00671 // the remaining dimensions are 0..n-1,n+1..N-1 00672 if (N-1 == 0) 00673 { 00674 shape[0] = 1; 00675 stride[0] = 0; 00676 } 00677 else 00678 { 00679 std::copy (m_shape.begin (), m_shape.begin () + M, shape.begin ()); 00680 std::copy (m_shape.begin () + M+1, m_shape.end (), 00681 shape.begin () + M); 00682 std::copy (m_stride.begin (), m_stride.begin () + M, stride.begin ()); 00683 std::copy (m_stride.begin () + M+1, m_stride.end (), 00684 stride.begin () + M); 00685 } 00686 return MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type> 00687 (shape, stride, m_ptr + d * m_stride[M]); 00688 } 00689 00690 #else // NO_OUT_OF_LINE_MEMBER_TEMPLATES 00691 template <unsigned int N, class T, class C, unsigned int M> 00692 MultiArrayView <N-M, T, C> 00693 bindOuterImpl(MultiArrayView <N, T, C> const & self, const TinyVector <int, M> &d) 00694 { 00695 TinyVector <int, M> stride; 00696 stride.init (self.stride().begin () + N-M, self.stride().end ()); 00697 typename MultiArrayView <N, T, C>::pointer ptr = self.data() + dot (d, stride); 00698 static const int NNew = (N-M == 0) ? 1 : N-M; 00699 TinyVector <int, NNew> inner_shape, inner_stride; 00700 if (N-M == 0) 00701 { 00702 inner_shape [0] = 1; 00703 inner_stride [0] = 0; 00704 } 00705 else 00706 { 00707 inner_shape.init (self.shape().begin (), self.shape().end () - M); 00708 inner_stride.init (self.stride().begin (), self.stride().end () - M); 00709 } 00710 return MultiArrayView <N-M, T, C> (inner_shape, inner_stride, ptr); 00711 } 00712 00713 template <unsigned int N, class T, class C, unsigned int M> 00714 MultiArrayView <N - M, T, StridedArrayTag> 00715 bindInnerImpl(MultiArrayView <N, T, C> const & self, const TinyVector <int, M> &d) 00716 { 00717 TinyVector <int, M> stride; 00718 stride.init (self.stride().begin (), self.stride().end () - N + M); 00719 typename MultiArrayView <N, T, C>::pointer ptr = self.data() + dot (d, stride); 00720 static const int NNew = (N-M == 0) ? 1 : N-M; 00721 TinyVector <int, NNew> outer_shape, outer_stride; 00722 if (N-M == 0) 00723 { 00724 outer_shape [0] = 1; 00725 outer_stride [0] = 0; 00726 } 00727 else 00728 { 00729 outer_shape.init (self.shape().begin () + M, self.shape().end ()); 00730 outer_stride.init (self.stride().begin () + M, self.stride().end ()); 00731 } 00732 return MultiArrayView <N-M, T, StridedArrayTag> 00733 (outer_shape, outer_stride, ptr); 00734 } 00735 00736 template <unsigned int M, unsigned int N, class T, class C> 00737 MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type > 00738 bindImpl(MultiArrayView <N, T, C> const & self, int d) 00739 { 00740 static const int NNew = (N-1 == 0) ? 1 : N-1; 00741 TinyVector <int, NNew> shape, stride; 00742 // the remaining dimensions are 0..n-1,n+1..N-1 00743 if (N-1 == 0) 00744 { 00745 shape[0] = 1; 00746 stride[0] = 0; 00747 } 00748 else 00749 { 00750 std::copy (self.shape().begin (), self.shape().begin () + M, shape.begin ()); 00751 std::copy (self.shape().begin () + M+1, self.shape().end (), 00752 shape.begin () + M); 00753 std::copy (self.stride().begin (), self.stride().begin () + M, stride.begin ()); 00754 std::copy (self.stride().begin () + M+1, self.stride().end (), 00755 stride.begin () + M); 00756 } 00757 return MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type> 00758 (shape, stride, self.data() + d * self.stride(M)); 00759 } 00760 00761 #endif // NO_OUT_OF_LINE_MEMBER_TEMPLATES 00762 00763 template <unsigned int N, class T, class C> 00764 MultiArrayView <N - 1, T, C> 00765 MultiArrayView <N, T, C>::bindOuter (int d) const 00766 { 00767 static const int NNew = (N-1 == 0) ? 1 : N-1; 00768 TinyVector <int, NNew> inner_shape, inner_stride; 00769 if (N-1 == 0) 00770 { 00771 inner_shape [0] = 1; 00772 inner_stride [0] = 0; 00773 } 00774 else 00775 { 00776 inner_shape.init (m_shape.begin (), m_shape.end () - 1); 00777 inner_stride.init (m_stride.begin (), m_stride.end () - 1); 00778 } 00779 return MultiArrayView <N-1, T, C> (inner_shape, inner_stride, 00780 m_ptr + d * m_stride [N-1]); 00781 } 00782 00783 template <unsigned int N, class T, class C> 00784 MultiArrayView <N - 1, T, StridedArrayTag> 00785 MultiArrayView <N, T, C>::bindInner (int d) const 00786 { 00787 static const int NNew = (N-1 == 0) ? 1 : N-1; 00788 TinyVector <int, NNew> outer_shape, outer_stride; 00789 if (N-1 == 0) 00790 { 00791 outer_shape [0] = 1; 00792 outer_stride [0] = 0; 00793 } 00794 else 00795 { 00796 outer_shape.init (m_shape.begin () + 1, m_shape.end ()); 00797 outer_stride.init (m_stride.begin () + 1, m_stride.end ()); 00798 } 00799 return MultiArrayView <N-1, T, StridedArrayTag> 00800 (outer_shape, outer_stride, m_ptr + d * m_stride [0]); 00801 } 00802 00803 template <unsigned int N, class T, class C> 00804 MultiArrayView <N - 1, T, StridedArrayTag> 00805 MultiArrayView <N, T, C>::bindAt (int n, int d) const 00806 { 00807 vigra_precondition ( 00808 n < static_cast <int> (N), 00809 "MultiArrayView <N, T, C>::bindAt(): dimension out of range."); 00810 static const int NNew = (N-1 == 0) ? 1 : N-1; 00811 TinyVector <int, NNew> shape, stride; 00812 // the remaining dimensions are 0..n-1,n+1..N-1 00813 if (N-1 == 0) 00814 { 00815 shape [0] = 1; 00816 stride [0] = 0; 00817 } 00818 else 00819 { 00820 std::copy (m_shape.begin (), m_shape.begin () + n, shape.begin ()); 00821 std::copy (m_shape.begin () + n+1, m_shape.end (), 00822 shape.begin () + n); 00823 std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin ()); 00824 std::copy (m_stride.begin () + n+1, m_stride.end (), 00825 stride.begin () + n); 00826 } 00827 return MultiArrayView <N-1, T, StridedArrayTag> 00828 (shape, stride, m_ptr + d * m_stride[n]); 00829 } 00830 00831 template <unsigned int N, class T, class C> 00832 MultiArrayView <N-1, T, StridedArrayTag> 00833 MultiArrayView <N, T, C>::bindRow (int d) const 00834 { 00835 return this->bindInner (d); 00836 } 00837 00838 template <unsigned int N, class T, class C> 00839 MultiArrayView <N-1, T, C> 00840 MultiArrayView <N, T, C>::bindColumn (int d) const 00841 { 00842 return this->bindOuter (d); 00843 } 00844 00845 /********************************************************/ 00846 /* */ 00847 /* MultiArray */ 00848 /* */ 00849 /********************************************************/ 00850 00851 /** \brief Main <TT>MultiArray</TT> class containing the memory 00852 management. 00853 00854 This class inherits the interface of MultiArrayView, and implements 00855 the memory ownership. 00856 MultiArray's are always unstrided, striding them creates a MultiArrayView. 00857 00858 <b>\#include</b> 00859 "<a href="multi_array_8hxx-source.html">vigra/multi_array.hxx</a>" 00860 00861 Namespace: vigra 00862 */ 00863 template <unsigned int N, class T, class A /* default already declared above */> 00864 class MultiArray : public MultiArrayView <N, T> 00865 { 00866 00867 public: 00868 00869 /** the allocator type used to allocate the memory 00870 */ 00871 typedef A allocator_type; 00872 00873 /** the view type associated with this array. 00874 */ 00875 typedef MultiArrayView <N, T> view_type; 00876 00877 /** the matrix type associated with this array. 00878 */ 00879 typedef MultiArray <N, T> matrix_type; 00880 00881 /** the array's value type 00882 */ 00883 typedef typename view_type::value_type value_type; 00884 00885 /** pointer type 00886 */ 00887 typedef typename view_type::pointer pointer; 00888 00889 /** const pointer type 00890 */ 00891 typedef typename view_type::const_pointer const_pointer; 00892 00893 /** reference type (result of operator[]) 00894 */ 00895 typedef typename view_type::reference reference; 00896 00897 /** const reference type (result of operator[] const) 00898 */ 00899 typedef typename view_type::const_reference const_reference; 00900 00901 /** size type 00902 */ 00903 typedef typename view_type::size_type size_type; 00904 00905 /** difference type (used for offsetting) 00906 */ 00907 typedef typename view_type::difference_type difference_type; 00908 00909 /** traverser type 00910 */ 00911 typedef typename detail::MultiIteratorChooser < 00912 UnstridedArrayTag>::template Traverser <N, T, T &, T *>::type 00913 traverser; 00914 00915 /** traverser type to const data 00916 */ 00917 typedef typename detail::MultiIteratorChooser < 00918 UnstridedArrayTag>::template Traverser <N, T, T const &, T const *>::type 00919 const_traverser; 00920 00921 /** sequential (random access) iterator type 00922 */ 00923 typedef T * iterator; 00924 00925 /** sequential (random access) const iterator type 00926 */ 00927 typedef T * const_iterator; 00928 00929 protected: 00930 00931 /** the allocator used to allocate the memory 00932 */ 00933 allocator_type m_alloc; 00934 00935 /** allocate memory for s pixels, write its address into the given 00936 pointer and initialize the pixels with init. 00937 */ 00938 void allocate (pointer &ptr, std::size_t s, const_reference init); 00939 00940 /** allocate memory for s pixels, write its address into the given 00941 pointer and initialize the linearized pixels to the values of init. 00942 */ 00943 void allocate (pointer &ptr, std::size_t s, const_pointer init); 00944 00945 /** deallocate the memory (of length s) starting at the given address. 00946 */ 00947 void deallocate (pointer &ptr, std::size_t s); 00948 00949 public: 00950 00951 /** default constructor 00952 */ 00953 MultiArray (); 00954 00955 /** construct with given shape 00956 */ 00957 MultiArray (const difference_type &shape); 00958 00959 /** construct from shape with an initial value 00960 */ 00961 MultiArray (const difference_type &shape, const_reference init); 00962 00963 /** construct from shape and copy values from the given array 00964 */ 00965 MultiArray (const difference_type &shape, const_pointer init); 00966 00967 /** copy constructor 00968 */ 00969 MultiArray (const MultiArray &rhs); 00970 00971 /** assignment.<br> 00972 <em>Note:</em> this operation invalidates all dependent objects 00973 (array views and iterators) 00974 */ 00975 MultiArray &operator= (const MultiArray &rhs); 00976 00977 /** destructor 00978 */ 00979 ~MultiArray (); 00980 00981 00982 /** change the shape and allocate new memory.<br> 00983 <em>Note:</em> this operation invalidates all dependent objects 00984 (array views and iterators) 00985 */ 00986 void reshape (const difference_type &shape) 00987 { 00988 reshape (shape, NumericTraits <T>::zero ()); 00989 } 00990 00991 /** change the shape, allocate new memory and initialize it 00992 with the given value.<br> 00993 <em>Note:</em> this operation invalidates all dependent objects 00994 (array views and iterators) 00995 */ 00996 void reshape (const difference_type &shape, const_reference init); 00997 00998 /** sequential iterator pointing to the first array element. 00999 */ 01000 iterator begin () 01001 { 01002 return data(); 01003 } 01004 01005 /** sequential iterator pointing beyond the last array element. 01006 */ 01007 iterator end () 01008 { 01009 return data() + elementCount(); 01010 } 01011 01012 /** sequential const iterator pointing to the first array element. 01013 */ 01014 const_iterator begin () const 01015 { 01016 return data(); 01017 } 01018 01019 /** sequential const iterator pointing beyond the last array element. 01020 */ 01021 const_iterator end () const 01022 { 01023 return data() + elementCount(); 01024 } 01025 }; 01026 01027 template <unsigned int N, class T, class A> 01028 MultiArray <N, T, A>::MultiArray () 01029 : MultiArrayView <N, T> (difference_type (0), difference_type (0), 0) 01030 {} 01031 01032 template <unsigned int N, class T, class A> 01033 MultiArray <N, T, A>::MultiArray (const difference_type &shape) 01034 : MultiArrayView <N, T> (shape, detail::defaultStride <actual_dimension> (shape), 0) 01035 { 01036 if (N == 0) 01037 { 01038 m_shape [0] = 1; 01039 m_stride [0] = 0; 01040 } 01041 allocate (m_ptr, elementCount (), NumericTraits<T>::zero ()); 01042 } 01043 01044 template <unsigned int N, class T, class A> 01045 MultiArray <N, T, A>::MultiArray (const difference_type &shape, 01046 const_reference init) 01047 : MultiArrayView <N, T> (shape, detail::defaultStride <actual_dimension> (shape), 0) 01048 { 01049 if (N == 0) 01050 { 01051 m_shape [0] = 1; 01052 m_stride [0] = 0; 01053 } 01054 allocate (m_ptr, elementCount (), init); 01055 } 01056 01057 template <unsigned int N, class T, class A> 01058 MultiArray <N, T, A>::MultiArray (const difference_type &shape, 01059 const_pointer init) 01060 : MultiArrayView <N, T> (shape, detail::defaultStride <actual_dimension> (shape), 0) 01061 { 01062 if (N == 0) 01063 { 01064 m_shape [0] = 1; 01065 m_stride [0] = 0; 01066 } 01067 allocate (m_ptr, elementCount (), init); 01068 } 01069 01070 template <unsigned int N, class T, class A> 01071 MultiArray <N, T, A>::MultiArray (const MultiArray &rhs) 01072 : MultiArrayView <N, T> (rhs.m_shape, rhs.m_stride, 0), 01073 m_alloc (rhs.m_alloc) 01074 { 01075 allocate (m_ptr, elementCount (), rhs.data ()); 01076 } 01077 01078 template <unsigned int N, class T, class A> 01079 MultiArray <N, T, A>::~MultiArray () 01080 { 01081 deallocate (m_ptr, elementCount ()); 01082 } 01083 01084 template <unsigned int N, class T, class A> 01085 MultiArray <N, T, A> & 01086 MultiArray <N, T, A>::operator= (const MultiArray &rhs) 01087 { 01088 if (this == &rhs) 01089 return *this; 01090 pointer new_ptr; 01091 allocate (new_ptr, rhs.elementCount (), rhs.data ()); 01092 deallocate (m_ptr, elementCount ()); 01093 m_alloc = rhs.m_alloc; 01094 m_shape = rhs.m_shape; 01095 m_stride = rhs.m_stride; 01096 m_ptr = new_ptr; 01097 return *this; 01098 } 01099 01100 template <unsigned int N, class T, class A> 01101 void MultiArray <N, T, A>::reshape (const difference_type & new_shape, 01102 const_reference init) 01103 { 01104 if (N== 0) 01105 return; 01106 01107 difference_type new_stride = detail::defaultStride <actual_dimension> (new_shape); 01108 std::size_t new_size = new_shape [actual_dimension-1] * new_stride [actual_dimension-1]; 01109 T *new_ptr; 01110 allocate (new_ptr, new_size, init); 01111 deallocate (m_ptr, elementCount ()); 01112 m_ptr = new_ptr; 01113 m_shape = new_shape; 01114 m_stride = new_stride; 01115 } 01116 01117 template <unsigned int N, class T, class A> 01118 void MultiArray <N, T, A>::allocate (pointer & ptr, std::size_t s, 01119 const_reference init) 01120 { 01121 ptr = m_alloc.allocate (s); 01122 std::size_t i; 01123 try { 01124 for (i = 0; i < s; ++i) 01125 m_alloc.construct (ptr + i, init); 01126 } 01127 catch (...) { 01128 for (std::size_t j = 0; j < i; ++j) 01129 m_alloc.destroy (ptr + j); 01130 m_alloc.deallocate (ptr, s); 01131 throw; 01132 } 01133 } 01134 01135 template <unsigned int N, class T, class A> 01136 void MultiArray <N, T, A>::allocate (pointer & ptr, std::size_t s, 01137 const_pointer init) 01138 { 01139 ptr = m_alloc.allocate (s); 01140 std::size_t i; 01141 try { 01142 for (i = 0; i < s; ++i, ++init) 01143 m_alloc.construct (ptr + i, *init); 01144 } 01145 catch (...) { 01146 for (std::size_t j = 0; j < i; ++j) 01147 m_alloc.destroy (ptr + j); 01148 m_alloc.deallocate (ptr, s); 01149 throw; 01150 } 01151 } 01152 01153 template <unsigned int N, class T, class A> 01154 void MultiArray <N, T, A>::deallocate (pointer & ptr, std::size_t s) 01155 { 01156 if (ptr == 0) 01157 return; 01158 for (std::size_t i = 0; i < s; ++i) 01159 m_alloc.destroy (ptr + i); 01160 m_alloc.deallocate (ptr, s); 01161 ptr = 0; 01162 } 01163 01164 template <class T> 01165 BasicImageView <T> 01166 makeBasicImageView (MultiArrayView <2, T, UnstridedArrayTag> &array) 01167 { 01168 return BasicImageView <T> (array.data (), array.shape (0), 01169 array.shape (1)); 01170 } 01171 01172 template <class T> 01173 BasicImageView <T> 01174 makeBasicImageView (MultiArray <3, T> &array) 01175 { 01176 vigra_precondition ( 01177 array.shape (0) == 1, "makeBasicImageView(): array.shape(0) must be 1."); 01178 return BasicImageView <T> (array.data (), 01179 array.shape (1), array.shape (2)); 01180 } 01181 01182 template <class T> 01183 BasicImageView <RGBValue<T> > 01184 makeRGBImageView (MultiArray<3, T> &array) 01185 { 01186 vigra_precondition ( 01187 array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3."); 01188 return BasicImageView <RGBValue<T> > ( 01189 reinterpret_cast <RGBValue <T> *> (array.data ()), 01190 array.shape (1), array.shape (2)); 01191 } 01192 01193 } // namespace vigra 01194 01195 #endif // VIGRA_MULTI_ARRAY_HXX
© Ullrich Köthe (koethe@informatik.uni-hamburg.de) |
html generated using doxygen and Python
|