[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]

details vigra/multi_array.hxx VIGRA

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.5.0, Dec 07 2006 )                                    */
00008 /*    The VIGRA Website is                                              */
00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00010 /*    Please direct questions, bug reports, and contributions to        */
00011 /*        koethe@informatik.uni-hamburg.de          or                  */
00012 /*        vigra@kogs1.informatik.uni-hamburg.de                         */
00013 /*                                                                      */
00014 /*    Permission is hereby granted, free of charge, to any person       */
00015 /*    obtaining a copy of this software and associated documentation    */
00016 /*    files (the "Software"), to deal in the Software without           */
00017 /*    restriction, including without limitation the rights to use,      */
00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00019 /*    sell copies of the Software, and to permit persons to whom the    */
00020 /*    Software is furnished to do so, subject to the following          */
00021 /*    conditions:                                                       */
00022 /*                                                                      */
00023 /*    The above copyright notice and this permission notice shall be    */
00024 /*    included in all copies or substantial portions of the             */
00025 /*    Software.                                                         */
00026 /*                                                                      */
00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00035 /*                                                                      */
00036 /************************************************************************/
00037 
00038 
00039 #ifndef VIGRA_MULTI_ARRAY_HXX
00040 #define VIGRA_MULTI_ARRAY_HXX
00041 
00042 #include <memory>
00043 #include <algorithm>
00044 #include "accessor.hxx"
00045 #include "tinyvector.hxx"
00046 #include "rgbvalue.hxx"
00047 #include "basicimageview.hxx"
00048 #include "imageiterator.hxx"
00049 #include "numerictraits.hxx"
00050 #include "multi_iterator.hxx"
00051 #include "metaprogramming.hxx"
00052 #include "mathutil.hxx"
00053 
00054 namespace vigra
00055 {
00056 
00057 namespace detail
00058 {
00059 /********************************************************/
00060 /*                                                      */
00061 /*                    defaultStride                     */
00062 /*                                                      */
00063 /********************************************************/
00064 
00065 /* generates the stride for a gapless shape.
00066 
00067     Namespace: vigra::detail
00068 */
00069 template <unsigned int N>
00070 TinyVector <ptrdiff_t, N> defaultStride(const TinyVector <ptrdiff_t, N> &shape)
00071 {
00072     TinyVector <ptrdiff_t, N> ret;
00073     ret [0] = 1;
00074     for (unsigned int i = 1; i < N; ++i)
00075         ret [i] = ret [i-1] * shape [i-1];
00076     return ret;
00077 }
00078 
00079 /********************************************************/
00080 /*                                                      */
00081 /*                     MaybeStrided                     */
00082 /*                                                      */
00083 /********************************************************/
00084 
00085 /* metatag implementing a test for marking MultiArrays that were
00086     indexed at the zero'th dimension as strided, and all others as
00087     unstrided.
00088 
00089 <b>\#include</b>
00090 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00091 
00092 Namespace: vigra::detail
00093 */
00094 template <unsigned int N>
00095 struct MaybeStrided
00096 {
00097     typedef UnstridedArrayTag type;
00098 };
00099 
00100 template <>
00101 struct MaybeStrided <0>
00102 {
00103     typedef StridedArrayTag type;
00104 };
00105 
00106 /********************************************************/
00107 /*                                                      */
00108 /*                MultiIteratorChooser                  */
00109 /*                                                      */
00110 /********************************************************/
00111 
00112 /* metatag implementing a test (by pattern matching) for marking
00113     MultiArrays that were indexed at the zero'th dimension as strided.
00114 
00115 <b>\#include</b>
00116 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00117 
00118 Namespace: vigra::detail
00119 */
00120 template <class O>
00121 struct MultiIteratorChooser
00122 {
00123     struct Nil {};
00124 
00125     template <unsigned int N, class T, class REFERENCE, class POINTER>
00126     struct Traverser
00127     {
00128         typedef Nil type;
00129     };
00130 };
00131 
00132 /********************************************************/
00133 /*                                                      */
00134 /*       MultiIteratorChooser <StridedArrayTag>         */
00135 /*                                                      */
00136 /********************************************************/
00137 
00138 /* specialization of the MultiIteratorChooser for strided arrays.
00139 
00140 <b>\#include</b>
00141 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00142 
00143 Namespace: vigra::detail
00144 */
00145 template <>
00146 struct MultiIteratorChooser <StridedArrayTag>
00147 {
00148     template <unsigned int N, class T, class REFERENCE, class POINTER>
00149     struct Traverser
00150     {
00151         typedef StridedMultiIterator <N, T, REFERENCE, POINTER> type;
00152     };
00153 };
00154 
00155 /********************************************************/
00156 /*                                                      */
00157 /*      MultiIteratorChooser <UnstridedArrayTag>        */
00158 /*                                                      */
00159 /********************************************************/
00160 
00161 /* specialization of the MultiIteratorChooser for unstrided arrays.
00162 
00163 <b>\#include</b>
00164 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00165 
00166 Namespace: vigra::detail
00167 */
00168 template <>
00169 struct MultiIteratorChooser <UnstridedArrayTag>
00170 {
00171     template <unsigned int N, class T, class REFERENCE, class POINTER>
00172     struct Traverser
00173     {
00174         typedef MultiIterator <N, T, REFERENCE, POINTER> type;
00175     };
00176 };
00177 
00178 /********************************************************/
00179 /*                                                      */
00180 /*                   helper functions                   */
00181 /*                                                      */
00182 /********************************************************/
00183 
00184 template <class DestIterator, class Shape, class T>
00185 void
00186 initMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<0>)
00187 {    
00188     DestIterator dend = d + shape[0];
00189     for(; d != dend; ++d)
00190     {
00191         *d = init;
00192     }
00193 }
00194 
00195 template <class DestIterator, class Shape, class T, int N>
00196 void
00197 initMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<N>)
00198 {    
00199     DestIterator dend = d + shape[N];
00200     for(; d != dend; ++d)
00201     {
00202         initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>());
00203     }
00204 }
00205 
00206 template <class SrcIterator, class Shape, class DestIterator>
00207 void
00208 copyMultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<0>)
00209 {    
00210     SrcIterator send = s + shape[0];
00211     for(; s != send; ++s, ++d)
00212     {
00213         *d = *s;
00214     }
00215 }
00216 
00217 template <class SrcIterator, class Shape, class DestIterator, int N>
00218 void
00219 copyMultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<N>)
00220 {    
00221     SrcIterator send = s + shape[N];
00222     for(; s != send; ++s, ++d)
00223     {
00224         copyMultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>());
00225     }
00226 }
00227 
00228 template <class SrcIterator, class Shape, class T, class ALLOC>
00229 void
00230 uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d, ALLOC & a, MetaInt<0>)
00231 {    
00232     SrcIterator send = s + shape[0];
00233     for(; s != send; ++s, ++d)
00234     {
00235         a.construct(d, *s);
00236     }
00237 }
00238 
00239 template <class SrcIterator, class Shape, class T, class ALLOC, int N>
00240 void
00241 uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d, ALLOC & a, MetaInt<N>)
00242 {    
00243     SrcIterator send = s + shape[N];
00244     for(; s != send; ++s)
00245     {
00246         uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1>());
00247     }
00248 }
00249 
00250 template <class SrcIterator, class Shape, class T>
00251 void
00252 squaredNormOfMultiArray(SrcIterator s, Shape const & shape, T & result, MetaInt<0>)
00253 {    
00254     SrcIterator send = s + shape[0];
00255     for(; s != send; ++s)
00256     {
00257         result += *s * *s;
00258     }
00259 }
00260 
00261 template <class SrcIterator, class Shape, class T, int N>
00262 void
00263 squaredNormOfMultiArray(SrcIterator s, Shape const & shape, T & result, MetaInt<N>)
00264 {    
00265     SrcIterator send = s + shape[N];
00266     for(; s != send; ++s)
00267     {
00268         squaredNormOfMultiArray(s.begin(), shape, result, MetaInt<N-1>());
00269     }
00270 }
00271 
00272 
00273 } // namespace detail
00274 
00275 /********************************************************/
00276 /*                                                      */
00277 /*                     MultiArrayView                   */
00278 /*                                                      */
00279 /********************************************************/
00280 
00281 // forward declaration
00282 template <unsigned int N, class T, class C = UnstridedArrayTag>
00283 class MultiArrayView;
00284 template <unsigned int N, class T, class A = std::allocator<T> >
00285 class MultiArray;
00286 
00287 /** \brief Base class for, and view to, \ref vigra::MultiArray.
00288 
00289 This class implements the interface of both MultiArray and
00290 MultiArrayView.  By default, MultiArrayViews are tagged as
00291 unstrided. If necessary, strided arrays are constructed automatically
00292 by calls to a variant of the bind...() function.
00293 
00294 If you want to apply an algorithm requiring an image to a
00295 <tt>MultiArrayView</tt> of appropriate (2-dimensional) shape, you can
00296 create a \ref vigra::BasicImageView that acts as a wrapper with the
00297 necessary interface -- see \ref MultiArrayToImage.
00298 
00299 The template parameter are as follows
00300 \code
00301     N: the array dimension
00302 
00303     T: the type of the array elements
00304 
00305     C: a tag determining whether the array's inner dimension is strided
00306        or not. An array is unstrided if the array elements occupy consecutive
00307        memory location, strided if there is an offset in between (e.g.
00308        when a view is created that skips every other array element).
00309        The compiler can generate faster code for unstrided arrays.
00310        Possible values: UnstridedArrayTag (default), StridedArrayTag
00311 \endcode
00312 
00313 <b>\#include</b>
00314 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00315 
00316 Namespace: vigra
00317 */
00318 template <unsigned int N, class T, class C>
00319 class MultiArrayView
00320 {
00321 public:
00322 
00323         /** the array's actual dimensionality.
00324             This ensures that MultiArrayView can also be used for
00325             scalars (that is, when <tt>N == 0</tt>). Calculated as:<br>
00326             \code
00327             actual_dimension = (N==0) ? 1 : N
00328             \endcode
00329          */
00330     enum ActualDimension { actual_dimension = (N==0) ? 1 : N };
00331 
00332         /** the array's value type
00333          */
00334     typedef T value_type;
00335 
00336         /** reference type (result of operator[])
00337          */
00338     typedef value_type &reference;
00339 
00340         /** const reference type (result of operator[] const)
00341          */
00342     typedef const value_type &const_reference;
00343 
00344         /** pointer type
00345          */
00346     typedef value_type *pointer;
00347 
00348         /** const pointer type
00349          */
00350     typedef const value_type *const_pointer;
00351 
00352         /** difference type (used for offsetting)
00353          */
00354     typedef TinyVector <ptrdiff_t, actual_dimension> difference_type;
00355 
00356         /** size type
00357          */
00358     typedef difference_type size_type;
00359 
00360         /** traverser (MultiIterator) type
00361          */
00362     typedef typename detail::MultiIteratorChooser <
00363         C>::template Traverser <actual_dimension, T, T &, T *>::type traverser;
00364 
00365         /** const traverser (MultiIterator) type
00366          */
00367     typedef typename detail::MultiIteratorChooser <
00368         C>::template Traverser <actual_dimension, T, T const &, T const *>::type const_traverser;
00369 
00370         /** the view type associated with this array.
00371          */
00372     typedef MultiArrayView <N, T, C> view_type;
00373 
00374         /** the matrix type associated with this array.
00375          */
00376     typedef MultiArray <N, T> matrix_type;
00377 
00378         /** the squared norm type (return type of array.squaredNorm()).
00379          */
00380     typedef typename NormTraits<T>::SquaredNormType SquaredNormType;
00381 
00382         /** the norm type (return type of array.norm()).
00383          */
00384     typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
00385 
00386 protected:
00387 
00388     typedef typename difference_type::value_type diff_zero_t;
00389 
00390         /** the shape of the image pointed to is stored here.
00391         */
00392     difference_type m_shape;
00393 
00394         /** the strides (offset of a sample to the next) for every dimension
00395             are stored here.
00396         */
00397     difference_type m_stride;
00398 
00399         /** pointer to the image.
00400          */
00401     pointer m_ptr;
00402 
00403 public:
00404 
00405         /** default constructor: create an empty image of size 0.
00406          */
00407     MultiArrayView ()
00408         : m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0)
00409     {}
00410 
00411 
00412         /** construct from shape and pointer
00413          */
00414     MultiArrayView (const difference_type &shape, pointer ptr);
00415 
00416         /** construct from shape, strides (offset of a sample to the next)
00417             for every dimension) and pointer
00418          */
00419     MultiArrayView (const difference_type &shape,
00420                     const difference_type &stride,
00421                     pointer ptr);
00422 
00423         /** array access.
00424          */
00425     reference operator[] (const difference_type &d)
00426     {
00427         return m_ptr [dot (d, m_stride)];
00428     }
00429 
00430         /** array access.
00431          */
00432     const_reference operator[] (const difference_type &d) const
00433     {
00434         return m_ptr [dot (d, m_stride)];
00435     }
00436 
00437         /** 1D array access. Use only if N == 1.
00438          */
00439     reference operator() (int x)
00440     {
00441         return m_ptr [m_stride[0]*x];
00442     }
00443 
00444         /** 2D array access. Use only if N == 2.
00445          */
00446     reference operator() (int x, int y)
00447     {
00448         return m_ptr [m_stride[0]*x + m_stride[1]*y];
00449     }
00450 
00451         /** 3D array access. Use only if N == 3.
00452          */
00453     reference operator() (int x, int y, int z)
00454     {
00455         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
00456     }
00457 
00458         /** 4D array access. Use only if N == 4.
00459          */
00460     reference operator() (int x, int y, int z, int u)
00461     {
00462         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
00463     }
00464 
00465         /** 5D array access. Use only if N == 5.
00466          */
00467     reference operator() (int x, int y, int z, int u, int v)
00468     {
00469         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
00470     }
00471 
00472         /** 1D const array access. Use only if N == 1.
00473          */
00474     const_reference operator() (int x) const
00475     {
00476         return m_ptr [m_stride[0]*x];
00477     }
00478 
00479         /** 2D const array access. Use only if N == 2.
00480          */
00481     const_reference operator() (int x, int y) const
00482     {
00483         return m_ptr [m_stride[0]*x + m_stride[1]*y];
00484     }
00485 
00486         /** 3D const array access. Use only if N == 3.
00487          */
00488     const_reference operator() (int x, int y, int z) const
00489     {
00490         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
00491     }
00492 
00493         /** 4D const array access. Use only if N == 4.
00494          */
00495     const_reference operator() (int x, int y, int z, int u) const
00496     {
00497         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
00498     }
00499 
00500         /** 5D const array access. Use only if N == 5.
00501          */
00502     const_reference operator() (int x, int y, int z, int u, int v) const
00503     {
00504         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
00505     }
00506 
00507         /** Init with a constant.
00508          */
00509     template <class U>
00510     void init(const U & init);
00511 
00512         /** Copy the data of the right-hand array (array shapes must match).
00513          */
00514     template <class U, class CN>
00515     void copy(const MultiArrayView <N, U, CN>& rhs);
00516 
00517         /** bind the M outmost dimensions to certain indices.
00518             this reduces the dimensionality of the image to
00519             max { 1, N-M }
00520         */
00521     template <unsigned int M>
00522     MultiArrayView <N-M, T, C> bindOuter (const TinyVector <ptrdiff_t, M> &d) const;
00523 
00524         /** bind the M innermost dimensions to certain indices.
00525             this reduces the dimensionality of the image to
00526             max { 1, N-M }
00527         */
00528     template <unsigned int M>
00529     MultiArrayView <N-M, T, StridedArrayTag>
00530     bindInner (const TinyVector <ptrdiff_t, M> &d) const;
00531 
00532         /** bind dimension M to index d.
00533             this reduces the dimensionality of the image to
00534             max { 1, N-1 }
00535          */
00536     template <unsigned int M>
00537     MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type >
00538     bind (int d) const;
00539 
00540         /** bind the outmost dimension to a certain index.
00541             this reduces the dimensionality of the image to
00542             max { 1, N-1 }
00543         */
00544     MultiArrayView <N-1, T, C> bindOuter (int d) const;
00545 
00546         /** bind the innermost dimension to a certain index.
00547             this reduces the dimensionality of the image to
00548             max { 1, N-1 }
00549         */
00550     MultiArrayView <N-1, T, StridedArrayTag> bindInner (int d) const;
00551 
00552         /** bind dimension m to index d.
00553             this reduces the dimensionality of the image to
00554             max { 1, N-1 }
00555          */
00556     MultiArrayView <N-1, T, StridedArrayTag>
00557     bindAt (int m, int d) const;
00558 
00559         /** create a rectangular subarray that spans between the
00560             points p and q, where p is in the subarray, q not.
00561         */
00562     MultiArrayView subarray (const difference_type &p,
00563                              const difference_type &q) const
00564     {
00565         const int offset = dot (m_stride, p);
00566         return MultiArrayView (q - p, m_stride, m_ptr + offset);
00567     }
00568 
00569         /** apply an additional striding to the image, thereby reducing
00570             the shape of the array.
00571             for example, multiplying the stride of dimension one by three
00572             turns an appropriately layed out (interleaved) rgb image into
00573             a single band image.
00574         */
00575     MultiArrayView <N, T, StridedArrayTag>
00576     stridearray (const difference_type &s) const
00577     {
00578         difference_type shape = m_shape;
00579         for (unsigned int i = 0; i < actual_dimension; ++i)
00580             shape [i] /= s [i];
00581         return MultiArrayView <N, T, StridedArrayTag>
00582             (shape, m_stride * s, m_ptr);
00583     }
00584 
00585         /** number of the elements in the array.
00586          */
00587     std::size_t elementCount () const
00588     {
00589         std::size_t ret = m_shape[0];
00590         for(unsigned int i = 1; i < actual_dimension; ++i)
00591             ret *= m_shape[i];
00592         return ret;
00593     }
00594 
00595         /** return the array's size.
00596          */
00597     const size_type & size () const
00598     {
00599         return m_shape;
00600     }
00601 
00602         /** return the array's shape (same as the <tt>size()</tt>).
00603          */
00604     const difference_type & shape () const
00605     {
00606         return m_shape;
00607     }
00608 
00609         /** return the array's size at a certain dimension.
00610          */
00611     int size (int n) const
00612     {
00613         return m_shape [n];
00614     }
00615 
00616         /** return the array's shape at a certain dimension 
00617             (same as <tt>size(n)</tt>).
00618          */
00619     int shape (int n) const
00620     {
00621         return m_shape [n];
00622     }
00623 
00624         /** return the array's stride for every dimension.
00625          */
00626     const difference_type & stride () const
00627     {
00628         return m_stride;
00629     }
00630 
00631         /** return the array's stride at a certain dimension.
00632          */
00633     int stride (int n) const
00634     {
00635         return m_stride [n];
00636     }
00637 
00638         /** check whether the given point is in the array range.
00639          */
00640     bool isInside (difference_type const & p) const
00641     {
00642         for(int d=0; d<actual_dimension; ++d)
00643             if(p[d] < 0 || p[d] >= shape(d))
00644                 return false;
00645         return true;
00646     }
00647 
00648         /** return the squared norm of the array (sum of squares of the array elements).
00649          */
00650     SquaredNormType squaredNorm() const
00651     {
00652         SquaredNormType res = NumericTraits<SquaredNormType>::zero();  
00653         detail::squaredNormOfMultiArray(traverser_begin(), shape(), res, MetaInt<actual_dimension-1>());
00654         return res;
00655     }
00656 
00657         /** return the norm of the array (equals <tt>sqrt(array.squaredNorm())</tt>).
00658          */
00659     NormType norm() const
00660     {
00661         return sqrt(static_cast<typename SquareRootTraits<SquaredNormType>::SquareRootArgument>(this->squaredNorm()));
00662     }
00663 
00664         /** return the pointer to the image data
00665          */
00666     pointer data () const
00667     {
00668         return m_ptr;
00669     }
00670 
00671         /** returns the N-dimensional MultiIterator pointing
00672             to the first element in every dimension.
00673         */
00674     traverser traverser_begin ()
00675     {
00676         traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00677         return ret;
00678     }
00679 
00680         /** returns the N-dimensional MultiIterator pointing
00681             to the const first element in every dimension.
00682         */
00683     const_traverser traverser_begin () const
00684     {
00685         const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00686         return ret;
00687     }
00688 
00689         /** returns the N-dimensional MultiIterator pointing
00690             beyond the last element in dimension N, and to the
00691             first element in every other dimension.
00692         */
00693     traverser traverser_end ()
00694     {
00695         traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00696         ret += m_shape [actual_dimension-1];
00697         return ret;
00698     }
00699 
00700         /** returns the N-dimensional const MultiIterator pointing
00701             beyond the last element in dimension N, and to the
00702             first element in every other dimension.
00703         */
00704     const_traverser traverser_end () const
00705     {
00706         const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00707         ret += m_shape [actual_dimension-1];
00708         return ret;
00709     }
00710 
00711     view_type view ()
00712     {
00713         return *this;
00714     }
00715 };
00716 
00717 template <unsigned int N, class T, class C>
00718 MultiArrayView <N, T, C>::MultiArrayView (const difference_type &shape,
00719                                           pointer ptr)
00720     : m_shape (shape), m_stride (detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape)), m_ptr (ptr)
00721 {}
00722 
00723 template <unsigned int N, class T, class C>
00724 MultiArrayView <N, T, C>::MultiArrayView
00725 (const difference_type &shape, const difference_type &stride, pointer ptr)
00726     : m_shape (shape), m_stride (stride), m_ptr (ptr)
00727 {}
00728 
00729 template <unsigned int N, class T, class C>
00730 template <class U>
00731 void 
00732 MultiArrayView <N, T, C>::init(const U & init)
00733 {
00734     detail::initMultiArrayData(traverser_begin(), shape(), init, MetaInt<actual_dimension-1>());
00735 }
00736 
00737 template <unsigned int N, class T, class C>
00738 template <class U, class CN>
00739 void 
00740 MultiArrayView <N, T, C>::copy(const MultiArrayView <N, U, CN>& rhs)
00741 {
00742     if(this == &rhs)
00743         return;
00744     vigra_precondition (shape () == rhs.shape (),
00745         "MultiArrayView::copy(): shape mismatch.");
00746     detail::copyMultiArrayData(rhs.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>());
00747 }
00748 
00749 template <unsigned int N, class T, class C>
00750 template <unsigned int M>
00751 MultiArrayView <N-M, T, C>
00752 MultiArrayView <N, T, C>::bindOuter (const TinyVector <ptrdiff_t, M> &d) const
00753 {
00754     TinyVector <ptrdiff_t, M> stride;
00755     stride.init (m_stride.begin () + N-M, m_stride.end ());
00756     pointer ptr = m_ptr + dot (d, stride);
00757     static const int NNew = (N-M == 0) ? 1 : N-M;
00758     TinyVector <ptrdiff_t, NNew> inner_shape, inner_stride;
00759     if (N-M == 0)
00760     {
00761         inner_shape [0] = 1;
00762         inner_stride [0] = 0;
00763     }
00764     else
00765     {
00766         inner_shape.init (m_shape.begin (), m_shape.end () - M);
00767         inner_stride.init (m_stride.begin (), m_stride.end () - M);
00768     }
00769     return MultiArrayView <N-M, T, C> (inner_shape, inner_stride, ptr);
00770 }
00771 
00772 template <unsigned int N, class T, class C>
00773 template <unsigned int M>
00774 MultiArrayView <N - M, T, StridedArrayTag>
00775 MultiArrayView <N, T, C>::bindInner (const TinyVector <ptrdiff_t, M> &d) const
00776 {
00777     TinyVector <ptrdiff_t, M> stride;
00778     stride.init (m_stride.begin (), m_stride.end () - N + M);
00779     pointer ptr = m_ptr + dot (d, stride);
00780     static const int NNew = (N-M == 0) ? 1 : N-M;
00781     TinyVector <ptrdiff_t, NNew> outer_shape, outer_stride;
00782     if (N-M == 0)
00783     {
00784         outer_shape [0] = 1;
00785         outer_stride [0] = 0;
00786     }
00787     else
00788     {
00789         outer_shape.init (m_shape.begin () + M, m_shape.end ());
00790         outer_stride.init (m_stride.begin () + M, m_stride.end ());
00791     }
00792     return MultiArrayView <N-M, T, StridedArrayTag>
00793         (outer_shape, outer_stride, ptr);
00794 }
00795 
00796 template <unsigned int N, class T, class C>
00797 template <unsigned int M>
00798 MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type >
00799 MultiArrayView <N, T, C>::bind (int d) const
00800 {
00801     static const int NNew = (N-1 == 0) ? 1 : N-1;
00802     TinyVector <ptrdiff_t, NNew> shape, stride;
00803     // the remaining dimensions are 0..n-1,n+1..N-1
00804     if (N-1 == 0)
00805     {
00806         shape[0] = 1;
00807         stride[0] = 0;
00808     }
00809     else
00810     {
00811         std::copy (m_shape.begin (), m_shape.begin () + M, shape.begin ());
00812         std::copy (m_shape.begin () + M+1, m_shape.end (),
00813                    shape.begin () + M);
00814         std::copy (m_stride.begin (), m_stride.begin () + M, stride.begin ());
00815         std::copy (m_stride.begin () + M+1, m_stride.end (),
00816                    stride.begin () + M);
00817     }
00818     return MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type>
00819         (shape, stride, m_ptr + d * m_stride[M]);
00820 }
00821 
00822 template <unsigned int N, class T, class C>
00823 MultiArrayView <N - 1, T, C>
00824 MultiArrayView <N, T, C>::bindOuter (int d) const
00825 {
00826     static const int NNew = (N-1 == 0) ? 1 : N-1;
00827     TinyVector <ptrdiff_t, NNew> inner_shape, inner_stride;
00828     if (N-1 == 0)
00829     {
00830         inner_shape [0] = 1;
00831         inner_stride [0] = 0;
00832     }
00833     else
00834     {
00835         inner_shape.init (m_shape.begin (), m_shape.end () - 1);
00836         inner_stride.init (m_stride.begin (), m_stride.end () - 1);
00837     }
00838     return MultiArrayView <N-1, T, C> (inner_shape, inner_stride,
00839                                        m_ptr + d * m_stride [N-1]);
00840 }
00841 
00842 template <unsigned int N, class T, class C>
00843 MultiArrayView <N - 1, T, StridedArrayTag>
00844 MultiArrayView <N, T, C>::bindInner (int d) const
00845 {
00846     static const int NNew = (N-1 == 0) ? 1 : N-1;
00847     TinyVector <ptrdiff_t, NNew> outer_shape, outer_stride;
00848     if (N-1 == 0)
00849     {
00850         outer_shape [0] = 1;
00851         outer_stride [0] = 0;
00852     }
00853     else
00854     {
00855         outer_shape.init (m_shape.begin () + 1, m_shape.end ());
00856         outer_stride.init (m_stride.begin () + 1, m_stride.end ());
00857     }
00858     return MultiArrayView <N-1, T, StridedArrayTag>
00859         (outer_shape, outer_stride, m_ptr + d * m_stride [0]);
00860 }
00861 
00862 template <unsigned int N, class T, class C>
00863 MultiArrayView <N - 1, T, StridedArrayTag>
00864 MultiArrayView <N, T, C>::bindAt (int n, int d) const
00865 {
00866     vigra_precondition (
00867         n < static_cast <int> (N),
00868         "MultiArrayView <N, T, C>::bindAt(): dimension out of range.");
00869     static const int NNew = (N-1 == 0) ? 1 : N-1;
00870     TinyVector <ptrdiff_t, NNew> shape, stride;
00871     // the remaining dimensions are 0..n-1,n+1..N-1
00872     if (N-1 == 0)
00873     {
00874         shape [0] = 1;
00875         stride [0] = 0;
00876     }
00877     else
00878     {
00879         std::copy (m_shape.begin (), m_shape.begin () + n, shape.begin ());
00880         std::copy (m_shape.begin () + n+1, m_shape.end (),
00881                    shape.begin () + n);
00882         std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin ());
00883         std::copy (m_stride.begin () + n+1, m_stride.end (),
00884                    stride.begin () + n);
00885     }
00886     return MultiArrayView <N-1, T, StridedArrayTag>
00887         (shape, stride, m_ptr + d * m_stride[n]);
00888 }
00889 
00890 /********************************************************/
00891 /*                                                      */
00892 /*                          norm                        */
00893 /*                                                      */
00894 /********************************************************/
00895 
00896 template <unsigned int N, class T, class C>
00897 struct NormTraits<MultiArrayView <N, T, C> >
00898 {
00899     typedef MultiArrayView <N, T, C> Type;
00900     typedef typename Type::SquaredNormType SquaredNormType;
00901     typedef typename Type::NormType NormType;
00902 };
00903 
00904 template <unsigned int N, class T, class C>
00905 inline typename MultiArrayView <N, T, C>::SquaredNormType
00906 squaredNorm(MultiArrayView <N, T, C> const & a)
00907 {
00908     return a.squaredNorm();
00909 }
00910 
00911 template <unsigned int N, class T, class C>
00912 inline typename MultiArrayView <N, T, C>::NormType
00913 norm(MultiArrayView <N, T, C> const & a)
00914 {
00915     return a.norm();
00916 }
00917 
00918 /********************************************************/
00919 /*                                                      */
00920 /*                       MultiArray                     */
00921 /*                                                      */
00922 /********************************************************/
00923 
00924 /** \brief Main <TT>MultiArray</TT> class containing the memory
00925     management.
00926 
00927 This class inherits the interface of MultiArrayView, and implements
00928 the memory ownership.
00929 MultiArray's are always unstrided, striding them creates a MultiArrayView.
00930 
00931 
00932 The template parameters are as follows
00933 \code
00934     N: the array dimension
00935 
00936     T: the type of the array elements
00937 
00938     A: the allocator used for internal storage management
00939        (default: std::allocator<T>)
00940 \endcode
00941 
00942 <b>\#include</b>
00943 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00944 
00945 Namespace: vigra
00946 */
00947 template <unsigned int N, class T, class A /* default already declared above */>
00948 class MultiArray : public MultiArrayView <N, T>
00949 {
00950 
00951 public:
00952     using MultiArrayView <N, T>::actual_dimension;
00953 
00954         /** the allocator type used to allocate the memory
00955          */
00956     typedef A allocator_type;
00957 
00958         /** the view type associated with this array.
00959          */
00960     typedef MultiArrayView <N, T> view_type;
00961 
00962         /** the matrix type associated with this array.
00963          */
00964     typedef MultiArray <N, T, A> matrix_type;
00965 
00966         /** the array's value type
00967          */
00968     typedef typename view_type::value_type value_type;
00969 
00970         /** pointer type
00971          */
00972     typedef typename view_type::pointer pointer;
00973 
00974         /** const pointer type
00975          */
00976     typedef typename view_type::const_pointer const_pointer;
00977 
00978         /** reference type (result of operator[])
00979          */
00980     typedef typename view_type::reference reference;
00981 
00982         /** const reference type (result of operator[] const)
00983          */
00984     typedef typename view_type::const_reference const_reference;
00985 
00986         /** size type
00987          */
00988     typedef typename view_type::size_type size_type;
00989 
00990         /** difference type (used for offsetting)
00991          */
00992     typedef typename view_type::difference_type difference_type;
00993 
00994         /** traverser type
00995          */
00996     typedef typename detail::MultiIteratorChooser <
00997         UnstridedArrayTag>::template Traverser <N, T, T &, T *>::type
00998     traverser;
00999 
01000         /** traverser type to const data
01001          */
01002     typedef typename detail::MultiIteratorChooser <
01003         UnstridedArrayTag>::template Traverser <N, T, T const &, T const *>::type
01004     const_traverser;
01005 
01006         /** sequential (random access) iterator type
01007          */
01008     typedef T * iterator;
01009 
01010         /** sequential (random access) const iterator type
01011          */
01012     typedef T * const_iterator;
01013 
01014         /** the squared norm type (return type of squaredNorm(array)).
01015          */
01016     typedef typename view_type::SquaredNormType SquaredNormType;
01017 
01018         /** the norm type (return type of norm(array)).
01019          */
01020     typedef typename view_type::NormType NormType;
01021 
01022 protected:
01023 
01024     typedef typename difference_type::value_type diff_zero_t;
01025 
01026         /** the allocator used to allocate the memory
01027          */
01028     allocator_type m_alloc;
01029 
01030         /** allocate memory for s pixels, write its address into the given
01031             pointer and initialize the pixels with init.
01032         */
01033     void allocate (pointer &ptr, std::size_t s, const_reference init);
01034 
01035         /** allocate memory for s pixels, write its address into the given
01036             pointer and initialize the linearized pixels to the values of init.
01037         */
01038     template <class U>
01039     void allocate (pointer &ptr, std::size_t s, U const * init);
01040 
01041         /** allocate memory, write its address into the given
01042             pointer and initialize it by copying the data from the given MultiArrayView.
01043         */
01044     template <class U, class C>
01045     void allocate (pointer &ptr, MultiArrayView<N, U, C> const & init);
01046 
01047         /** deallocate the memory (of length s) starting at the given address.
01048          */
01049     void deallocate (pointer &ptr, std::size_t s);
01050 
01051 public:
01052 
01053         /** default constructor
01054          */
01055     MultiArray ();
01056 
01057         /** construct with given allocator
01058          */
01059     MultiArray (allocator_type const & alloc);
01060 
01061         /** construct with given shape
01062          */
01063     explicit MultiArray (const difference_type &shape,
01064                          allocator_type const & alloc = allocator_type());
01065 
01066         /** construct from shape with an initial value
01067          */
01068     MultiArray (const difference_type &shape, const_reference init,
01069                          allocator_type const & alloc = allocator_type());
01070 
01071         /** construct from shape and copy values from the given array
01072          */
01073     MultiArray (const difference_type &shape, const_pointer init,
01074                          allocator_type const & alloc = allocator_type());
01075 
01076         /** copy constructor
01077          */
01078     MultiArray (const MultiArray &rhs);
01079 
01080         /** construct by copying from a MultiArrayView
01081          */
01082     template <class U, class C>
01083     MultiArray (const MultiArrayView<N, U, C>  &rhs,
01084                 allocator_type const & alloc = allocator_type());
01085 
01086         /** assignment.<br>
01087             If the size of \a rhs is the same as the left-hand side arrays's old size, only 
01088             the data are copied. Otherwise, new storage is allocated, which invalidates all 
01089             objects (array views, iterators) depending on the lhs array.
01090          */
01091     MultiArray &operator= (const MultiArray &rhs)
01092     {
01093         return this->operator=(static_cast<view_type const &>(rhs));
01094     }
01095 
01096         /** assignment from arbitrary MultiArrayView.<br>
01097             If the size of \a rhs is the same as the left-hand side arrays's old size, only 
01098             the data are copied. Otherwise, new storage is allocated, which invalidates all 
01099             objects (array views, iterators) depending on the lhs array.
01100          */
01101     template <class U, class C>
01102     MultiArray &operator= (const MultiArrayView<N, U, C> &rhs);
01103 
01104         /** destructor
01105          */
01106    ~MultiArray ();
01107 
01108 
01109         /** change the shape and allocate new memory.<br>
01110             <em>Note:</em> this operation invalidates all dependent objects
01111             (array views and iterators)
01112          */
01113     void reshape (const difference_type &shape)
01114     {
01115         reshape (shape, NumericTraits <T>::zero ());
01116     }
01117 
01118         /** change the shape, allocate new memory and initialize it
01119             with the given value.<br>
01120             <em>Note:</em> this operation invalidates all dependent objects
01121             (array views and iterators)
01122          */
01123     void reshape (const difference_type &shape, const_reference init);
01124 
01125         /** Swap the contents with another MultiArray. This is fast,
01126             because no data are copied, but only pointers and shapes swapped.
01127             <em>Note:</em> this operation invalidates all dependent objects
01128             (array views and iterators)
01129          */
01130     void swap (MultiArray & other);
01131 
01132         /** sequential iterator pointing to the first array element.
01133          */
01134     iterator begin ()
01135     {
01136         return this->data();
01137     }
01138 
01139         /** sequential iterator pointing beyond the last array element.
01140          */
01141     iterator end ()
01142     {
01143         return this->data() + this->elementCount();
01144     }
01145 
01146         /** sequential const iterator pointing to the first array element.
01147          */
01148     const_iterator begin () const
01149     {
01150         return this->data();
01151     }
01152 
01153         /** sequential const iterator pointing beyond the last array element.
01154          */
01155     const_iterator end () const
01156     {
01157         return this->data() + this->elementCount();
01158     }
01159 
01160         /** get the allocator.
01161          */
01162     allocator_type const & allocator () const
01163     {
01164         return m_alloc;
01165     }
01166 };
01167 
01168 template <unsigned int N, class T, class A>
01169 MultiArray <N, T, A>::MultiArray ()
01170     : MultiArrayView <N, T> (difference_type (diff_zero_t(0)), 
01171                              difference_type (diff_zero_t(0)), 0)
01172 {}
01173 
01174 template <unsigned int N, class T, class A>
01175 MultiArray <N, T, A>::MultiArray (allocator_type const & alloc)
01176     : MultiArrayView <N, T> (difference_type (diff_zero_t(0)), 
01177                              difference_type (diff_zero_t(0)), 0),
01178       m_alloc(alloc)
01179 {}
01180 
01181 template <unsigned int N, class T, class A>
01182 MultiArray <N, T, A>::MultiArray (const difference_type &shape,
01183                                   allocator_type const & alloc)
01184     : MultiArrayView <N, T> (shape, detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape), 0),
01185       m_alloc(alloc)
01186 {
01187     if (N == 0)
01188     {
01189         this->m_shape [0] = 1;
01190         this->m_stride [0] = 0;
01191     }
01192     allocate (this->m_ptr, this->elementCount (), NumericTraits<T>::zero ());
01193 }
01194 
01195 template <unsigned int N, class T, class A>
01196 MultiArray <N, T, A>::MultiArray (const difference_type &shape,
01197                                   const_reference init,
01198                                   allocator_type const & alloc)
01199     : MultiArrayView <N, T> (shape, detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape), 0),
01200       m_alloc(alloc)
01201 {
01202     if (N == 0)
01203     {
01204         this->m_shape [0] = 1;
01205         this->m_stride [0] = 0;
01206     }
01207     allocate (this->m_ptr, this->elementCount (), init);
01208 }
01209 
01210 template <unsigned int N, class T, class A>
01211 MultiArray <N, T, A>::MultiArray (const difference_type &shape,
01212                                   const_pointer init,
01213                                   allocator_type const & alloc)
01214     : MultiArrayView <N, T> (shape, detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape), 0),
01215       m_alloc(alloc)
01216 {
01217     if (N == 0)
01218     {
01219         this->m_shape [0] = 1;
01220         this->m_stride [0] = 0;
01221     }
01222     allocate (this->m_ptr, this->elementCount (), init);
01223 }
01224 
01225 template <unsigned int N, class T, class A>
01226 MultiArray <N, T, A>::MultiArray (const MultiArray &rhs)
01227     : MultiArrayView <N, T> (rhs.m_shape, rhs.m_stride, 0),
01228     m_alloc (rhs.m_alloc)
01229 {
01230     allocate (this->m_ptr, this->elementCount (), rhs.data ());
01231 }
01232 
01233 template <unsigned int N, class T, class A>
01234 template <class U, class C>
01235 MultiArray <N, T, A>::MultiArray (const MultiArrayView<N, U, C> &rhs,
01236                                   allocator_type const & alloc)
01237     : MultiArrayView <N, T> (rhs.shape(), 
01238                              detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (rhs.shape()), 0),
01239     m_alloc (alloc)
01240 {
01241     allocate (this->m_ptr, rhs); 
01242 }
01243 
01244 template <unsigned int N, class T, class A>
01245 MultiArray <N, T, A>::~MultiArray ()
01246 {
01247     deallocate (this->m_ptr, this->elementCount ());
01248 }
01249 
01250 template <unsigned int N, class T, class A>
01251 template <class U, class C>
01252 MultiArray <N, T, A> &
01253 MultiArray <N, T, A>::operator= (const MultiArrayView<N, U, C> &rhs)
01254 {
01255     if (this == &rhs)
01256         return *this;
01257     if (this->shape() == rhs.shape())
01258         this->copy(rhs);
01259     else
01260     {
01261         pointer new_ptr;
01262         allocate (new_ptr, rhs);
01263         deallocate (this->m_ptr, this->elementCount ());
01264         this->m_shape = rhs.shape();
01265         this->m_stride = rhs.stride();
01266         this->m_ptr = new_ptr;
01267     }
01268     return *this;
01269 }
01270 
01271 template <unsigned int N, class T, class A>
01272 void MultiArray <N, T, A>::reshape (const difference_type & new_shape,
01273                                     const_reference init)
01274 {
01275     if (N== 0)
01276         return;
01277 
01278     difference_type new_stride = detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (new_shape);
01279     std::size_t new_size = new_shape [MultiArrayView<N,T>::actual_dimension-1] * new_stride [MultiArrayView<N,T>::actual_dimension-1];
01280     T *new_ptr;
01281     allocate (new_ptr, new_size, init);
01282     deallocate (this->m_ptr, this->elementCount ());
01283     this->m_ptr = new_ptr;
01284     this->m_shape = new_shape;
01285     this->m_stride = new_stride;
01286 }
01287 
01288 
01289 template <unsigned int N, class T, class A>
01290 void MultiArray <N, T, A>::swap (MultiArray <N, T, A> & other)
01291 {
01292     if (this == &other)
01293         return;
01294     std::swap(this->m_shape,  other.m_shape);
01295     std::swap(this->m_stride, other.m_stride);
01296     std::swap(this->m_ptr,    other.m_ptr);
01297     std::swap(this->m_alloc,  other.m_alloc);
01298 }
01299 
01300 template <unsigned int N, class T, class A>
01301 void MultiArray <N, T, A>::allocate (pointer & ptr, std::size_t s,
01302                                      const_reference init)
01303 {
01304     ptr = m_alloc.allocate (s);
01305     std::size_t i;
01306     try {
01307         for (i = 0; i < s; ++i)
01308             m_alloc.construct (ptr + i, init);
01309     }
01310     catch (...) {
01311         for (std::size_t j = 0; j < i; ++j)
01312             m_alloc.destroy (ptr + j);
01313         m_alloc.deallocate (ptr, s);
01314         throw;
01315     }
01316 }
01317 
01318 template <unsigned int N, class T, class A>
01319 template <class U>
01320 void MultiArray <N, T, A>::allocate (pointer & ptr, std::size_t s,
01321                                      U const * init)
01322 {
01323     ptr = m_alloc.allocate (s);
01324     std::size_t i;
01325     try {
01326         for (i = 0; i < s; ++i, ++init)
01327             m_alloc.construct (ptr + i, *init);
01328     }
01329     catch (...) {
01330         for (std::size_t j = 0; j < i; ++j)
01331             m_alloc.destroy (ptr + j);
01332         m_alloc.deallocate (ptr, s);
01333         throw;
01334     }
01335 }
01336 
01337 template <unsigned int N, class T, class A>
01338 template <class U, class C>
01339 void MultiArray <N, T, A>::allocate (pointer & ptr, MultiArrayView<N, U, C> const & init)
01340 {
01341     std::size_t s = init.elementCount();
01342     ptr = m_alloc.allocate (s);
01343     pointer p = ptr;
01344     try {
01345         detail::uninitializedCopyMultiArrayData(init.traverser_begin(), init.shape(), 
01346                                                 p, m_alloc, MetaInt<actual_dimension-1>());
01347     }
01348     catch (...) {
01349         for (pointer pp = ptr; pp < p; ++pp)
01350             m_alloc.destroy (pp);
01351         m_alloc.deallocate (ptr, s);
01352         throw;
01353     }
01354 }
01355 
01356 template <unsigned int N, class T, class A>
01357 void MultiArray <N, T, A>::deallocate (pointer & ptr, std::size_t s)
01358 {
01359     if (ptr == 0)
01360         return;
01361     for (std::size_t i = 0; i < s; ++i)
01362         m_alloc.destroy (ptr + i);
01363     m_alloc.deallocate (ptr, s);
01364     ptr = 0;
01365 }
01366 
01367 /********************************************************/
01368 /*                                                      */
01369 /*                       NormTraits                     */
01370 /*                                                      */
01371 /********************************************************/
01372 
01373 template <unsigned int N, class T, class A>
01374 struct NormTraits<MultiArray <N, T, A> >
01375 {
01376     typedef MultiArray <N, T, A> Type;
01377     typedef typename Type::SquaredNormType SquaredNormType;
01378     typedef typename Type::NormType NormType;
01379 };
01380 
01381 /********************************************************/
01382 /*                                                      */
01383 /*              argument object factories               */
01384 /*                                                      */
01385 /********************************************************/
01386 
01387 template <unsigned int N, class T, class C>
01388 inline triple<typename MultiArrayView<N,T,C>::const_traverser,
01389               typename MultiArrayView<N,T,C>::difference_type,
01390               typename AccessorTraits<T>::default_const_accessor >
01391 srcMultiArrayRange( MultiArrayView<N,T,C> const & array )
01392 {
01393     return triple<typename MultiArrayView<N,T,C>::const_traverser,
01394                   typename MultiArrayView<N,T,C>::difference_type,
01395                   typename AccessorTraits<T>::default_const_accessor >
01396       ( array.traverser_begin(),
01397         array.shape(),
01398         typename AccessorTraits<T>::default_const_accessor() );
01399 }
01400 
01401 template <unsigned int N, class T, class C, class Accessor>
01402 inline triple<typename MultiArrayView<N,T,C>::const_traverser,
01403               typename MultiArrayView<N,T,C>::difference_type,
01404               Accessor >
01405 srcMultiArrayRange( MultiArrayView<N,T,C> const & array, Accessor a )
01406 {
01407     return triple<typename MultiArrayView<N,T,C>::const_traverser,
01408                   typename MultiArrayView<N,T,C>::difference_type,
01409                   Accessor >
01410       ( array.traverser_begin(),
01411         array.shape(),
01412         a);
01413 }
01414 
01415 template <unsigned int N, class T, class C>
01416 inline pair<typename MultiArrayView<N,T,C>::const_traverser,
01417             typename AccessorTraits<T>::default_const_accessor >
01418 srcMultiArray( MultiArrayView<N,T,C> const & array )
01419 {
01420     return pair<typename MultiArrayView<N,T,C>::const_traverser,
01421                 typename AccessorTraits<T>::default_const_accessor >
01422       ( array.traverser_begin(),
01423         typename AccessorTraits<T>::default_const_accessor() );
01424 }
01425 
01426 template <unsigned int N, class T, class C, class Accessor>
01427 inline pair<typename MultiArrayView<N,T,C>::const_traverser,
01428             Accessor >
01429 srcMultiArray( MultiArrayView<N,T,C> const & array, Accessor a )
01430 {
01431     return pair<typename MultiArrayView<N,T,C>::const_traverser,
01432                 Accessor >
01433       ( array.traverser_begin(), a );
01434 }
01435 
01436 template <unsigned int N, class T, class C>
01437 inline triple<typename MultiArrayView<N,T,C>::traverser,
01438               typename MultiArrayView<N,T,C>::difference_type,
01439               typename AccessorTraits<T>::default_accessor >
01440 destMultiArrayRange( MultiArrayView<N,T,C> & array )
01441 {
01442     return triple<typename MultiArrayView<N,T,C>::traverser,
01443                   typename MultiArrayView<N,T,C>::difference_type,
01444                   typename AccessorTraits<T>::default_accessor >
01445       ( array.traverser_begin(),
01446         array.shape(),
01447         typename AccessorTraits<T>::default_accessor() );
01448 }
01449 
01450 template <unsigned int N, class T, class C, class Accessor>
01451 inline triple<typename MultiArrayView<N,T,C>::traverser,
01452               typename MultiArrayView<N,T,C>::difference_type,
01453               Accessor >
01454 destMultiArrayRange( MultiArrayView<N,T,C> & array, Accessor a )
01455 {
01456     return triple<typename MultiArrayView<N,T,C>::traverser,
01457                   typename MultiArrayView<N,T,C>::difference_type,
01458                   Accessor >
01459       ( array.traverser_begin(),
01460         array.shape(),
01461         a );
01462 }
01463 
01464 template <unsigned int N, class T, class C>
01465 inline pair<typename MultiArrayView<N,T,C>::traverser,
01466             typename AccessorTraits<T>::default_accessor >
01467 destMultiArray( MultiArrayView<N,T,C> & array )
01468 {
01469     return pair<typename MultiArrayView<N,T,C>::traverser,
01470                 typename AccessorTraits<T>::default_accessor >
01471         ( array.traverser_begin(),
01472           typename AccessorTraits<T>::default_accessor() );
01473 }
01474 
01475 template <unsigned int N, class T, class C, class Accessor>
01476 inline pair<typename MultiArrayView<N,T,C>::traverser,
01477             Accessor >
01478 destMultiArray( MultiArrayView<N,T,C> & array, Accessor a )
01479 {
01480     return pair<typename MultiArrayView<N,T,C>::traverser,
01481                 Accessor >
01482         ( array.traverser_begin(), a );
01483 }
01484 
01485 /********************************************************/
01486 /*                                                      */
01487 /*                  makeBasicImageView                  */
01488 /*                                                      */
01489 /********************************************************/
01490 
01491 /** \addtogroup MultiArrayToImage Wrap a \ref vigra::MultiArrayView in
01492                                   a \ref vigra::BasicImageView
01493 */
01494 //@{
01495 /** Create a \ref vigra::BasicImageView from an unstrided 2-dimensional
01496     \ref vigra::MultiArrayView.
01497 
01498     The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
01499     as the original \ref vigra::MultiArrayView.
01500 */
01501 template <class T>
01502 BasicImageView <T>
01503 makeBasicImageView (MultiArrayView <2, T, UnstridedArrayTag> const &array)
01504 {
01505     return BasicImageView <T> (array.data (), array.shape (0),
01506                                array.shape (1));
01507 }
01508 
01509 /** Create a \ref vigra::BasicImageView from a 3-dimensional
01510     \ref vigra::MultiArray.
01511 
01512     This wrapper flattens the two innermost dimensions of the array
01513     into single rows of the resulting image.
01514     The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
01515     as the original \ref vigra::MultiArray.
01516 */
01517 template <class T>
01518 BasicImageView <T>
01519 makeBasicImageView (MultiArray <3, T> const &array)
01520 {
01521     return BasicImageView <T> (array.data (),
01522                                array.shape (0)*array.shape (1), array.shape (2));
01523 }
01524 
01525 /** Create a \ref vigra::BasicImageView from a 3-dimensional
01526     \ref vigra::MultiArray.
01527 
01528     This wrapper only works if <tt>T</tt> is a scalar type and the
01529     array's innermost dimension has size 3. It then re-interprets
01530     the data array as a 2-dimensional array with value_type
01531     <tt>RGBValue&lt; T &gt;</tt>.
01532 */
01533 template <class T>
01534 BasicImageView <RGBValue<T> >
01535 makeRGBImageView (MultiArray<3, T> const &array)
01536 {
01537     vigra_precondition (
01538         array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3.");
01539     return BasicImageView <RGBValue<T> > (
01540         reinterpret_cast <RGBValue <T> *> (array.data ()),
01541         array.shape (1), array.shape (2));
01542 }
01543 
01544 //@}
01545 
01546 } // namespace vigra
01547 
01548 #endif // VIGRA_MULTI_ARRAY_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.5.0 (7 Dec 2006)