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