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

details vigra/multi_array.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 2003 by Gunnar Kedenburg                     */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.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)