[ 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.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)