vigra - vigra/multi_pointoperators.hxx Source File

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

vigra/multi_pointoperators.hxx |

    00001 //-- -*- c++ -*-
    00002 /************************************************************************/
    00003 /*                                                                      */
    00004 /*      Copyright 2003 by Ullrich Koethe, B. Seppke, F. Heinrich        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    The VIGRA Website is                                              */
    00008 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00009 /*    Please direct questions, bug reports, and contributions to        */
    00010 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00011 /*        vigra@informatik.uni-hamburg.de                               */
    00012 /*                                                                      */
    00013 /*    Permission is hereby granted, free of charge, to any person       */
    00014 /*    obtaining a copy of this software and associated documentation    */
    00015 /*    files (the "Software"), to deal in the Software without           */
    00016 /*    restriction, including without limitation the rights to use,      */
    00017 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00018 /*    sell copies of the Software, and to permit persons to whom the    */
    00019 /*    Software is furnished to do so, subject to the following          */
    00020 /*    conditions:                                                       */
    00021 /*                                                                      */
    00022 /*    The above copyright notice and this permission notice shall be    */
    00023 /*    included in all copies or substantial portions of the             */
    00024 /*    Software.                                                         */
    00025 /*                                                                      */
    00026 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00027 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00028 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00029 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00030 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00031 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00032 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00033 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00034 /*                                                                      */
    00035 /************************************************************************/
    00036
    00037 #ifndef VIGRA_MULTI_POINTOPERATORS_H
    00038 #define VIGRA_MULTI_POINTOPERATORS_H
    00039
    00040 #include "initimage.hxx"
    00041 #include "copyimage.hxx"
    00042 #include "transformimage.hxx"
    00043 #include "combineimages.hxx"
    00044 #include "inspectimage.hxx"
    00045 #include "multi_array.hxx"
    00046 #include "metaprogramming.hxx"
    00047 #include "inspector_passes.hxx"
    00048
    00049
    00050
    00051 namespace vigra
    00052 {
    00053
    00054 /** \addtogroup MultiPointoperators Point operators for multi-dimensional arrays.
    00055
    00056     Copy, transform, and inspect arbitrary dimensional arrays which are represented
    00057     by iterators compatible to \ref MultiIteratorPage. Note that are range is here
    00058     specified by a pair: an iterator referring to the first point of the array
    00059     and a shape object specifying the size of the (rectangular) ROI.
    00060
    00061     <b>\#include</b> <vigra/multi_pointoperators.hxx>
    00062 */
    00063 //@{
    00064
    00065 /********************************************************/
    00066 /*                                                      */
    00067 /*                    initMultiArray                    */
    00068 /*                                                      */
    00069 /********************************************************/
    00070
    00071 template <class Iterator, class Shape, class Accessor,
    00072           class VALUETYPE>
    00073 inline void
    00074 initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,  VALUETYPE const & v, MetaInt<0>)
    00075 {
    00076     initLine(s, s + shape[0], a, v);
    00077 }
    00078
    00079 template <class Iterator, class Shape, class Accessor,
    00080           class VALUETYPE, int N>
    00081 void
    00082 initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,
    00083                    VALUETYPE const & v, MetaInt<N>)
    00084 {
    00085     Iterator send = s + shape[N];
    00086     for(; s < send; ++s)
    00087     {
    00088         initMultiArrayImpl(s.begin(), shape, a, v, MetaInt<N-1>());
    00089     }
    00090 }
    00091
    00092 /** \brief Write a value to every pixel in a multi-dimensional array.
    00093
    00094     This function can be used to init the array which must be represented by
    00095     a pair of iterators compatible to \ref vigra::MultiIterator.
    00096     It uses an accessor to access the data elements. Note that the iterator range
    00097     must be specified by a shape object, because otherwise we could not control
    00098     the range simultaneously in all dimensions (this is a necessary consequence
    00099     of the \ref vigra::MultiIterator design).
    00100
    00101     The initial value can either be a constant of appropriate type (compatible with
    00102     the destination's value_type), or a functor with compatible result_type. These two
    00103     cases are automatically distinguished when <tt>FunctorTraits<FUNCTOR>::isInitializer</tt>
    00104     yields <tt>VigraTrueType</tt>. Since the functor is passed by <tt>const</tt> reference, its
    00105     <tt>operator()</tt> must be const, and its internal state may need to be <tt>mutable</tt>.
    00106
    00107     <b> Declarations:</b>
    00108
    00109     pass arguments explicitly:
    00110     \code
    00111     namespace vigra {
    00112         template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00113         void
    00114         initMultiArray(Iterator s, Shape const & shape, Accessor a,  VALUETYPE const & v);
    00115
    00116
    00117         template <class Iterator, class Shape, class Accessor, class FUNCTOR>
    00118         void
    00119         initMultiArray(Iterator s, Shape const & shape, Accessor a,  FUNCTOR const & f);
    00120     }
    00121     \endcode
    00122
    00123     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00124     \code
    00125     namespace vigra {
    00126         template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00127         void
    00128         initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE const & v);
    00129
    00130
    00131         template <class Iterator, class Shape, class Accessor, class FUNCTOR>
    00132         void
    00133         initMultiArray(triple<Iterator, Shape, Accessor> const & s, FUNCTOR const & f);
    00134     }
    00135     \endcode
    00136
    00137     <b> Usage:</b>
    00138
    00139     <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
    00140     Namespace: vigra
    00141
    00142     \code
    00143     typedef vigra::MultiArray<3, int> Array;
    00144     Array array(Array::size_type(100, 200, 50));
    00145
    00146     // zero the array
    00147     vigra::initMultiArray(destMultiArrayRange(array), 0);
    00148     \endcode
    00149
    00150     <b> Required Interface:</b>
    00151
    00152     The function accepts either a value that is copied into every destination element:
    00153
    00154     \code
    00155     MultiIterator begin;
    00156
    00157     Accessor accessor;
    00158     VALUETYPE v;
    00159
    00160     accessor.set(v, begin);
    00161     \endcode
    00162
    00163     or a functor that is called (without argument) at every location,
    00164     and the result is written into the current element. Internally,
    00165     functors are recognized by the meta function
    00166     <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> yielding <tt>VigraTrueType</tt>.
    00167     Make sure that your functor correctly defines <tt>FunctorTraits</tt> because
    00168     otherwise the code will not compile.
    00169
    00170     \code
    00171     MultiIterator begin;
    00172     Accessor accessor;
    00173
    00174     FUNCTOR f;
    00175     assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    00176
    00177     accessor.set(f(), begin);
    00178     \endcode
    00179
    00180
    00181 */
    00182 doxygen_overloaded_function(template <...> void initMultiArray)
    00183
    00184 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00185 inline void
    00186 initMultiArray(Iterator s, Shape const & shape, Accessor a,  VALUETYPE const & v)
    00187 {
    00188     initMultiArrayImpl(s, shape, a, v, MetaInt<Iterator::level>());
    00189 }
    00190
    00191 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00192 inline
    00193 void
    00194 initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE const & v)
    00195 {
    00196     initMultiArray(s.first, s.second, s.third, v);
    00197 }
    00198
    00199 /********************************************************/
    00200 /*                                                      */
    00201 /*                  initMultiArrayBorder                */
    00202 /*                                                      */
    00203 /********************************************************/
    00204
    00205 /** \brief Write value to the specified border values in the array.
    00206
    00207 */template <class Iterator, class Diff_type, class Accessor, class VALUETYPE>
    00208 inline void initMultiArrayBorder( Iterator upperleft, Diff_type shape,
    00209                                   Accessor a,  int border_width, VALUETYPE v)
    00210 {
    00211     Diff_type border(shape);
    00212     for(unsigned int dim=0; dim<shape.size(); dim++){
    00213         border[dim] = (border_width > shape[dim]) ? shape[dim] : border_width;
    00214     }
    00215
    00216     for(unsigned int dim=0; dim<shape.size(); dim++){
    00217         Diff_type  start(shape),
    00218                    offset(shape);
    00219         start = start-shape;
    00220         offset[dim]=border[dim];
    00221
    00222         initMultiArray(upperleft+start, offset, a, v);
    00223
    00224         start[dim]=shape[dim]-border[dim];
    00225         initMultiArray(upperleft+start, offset, a, v);
    00226     }
    00227 }
    00228
    00229 template <class Iterator, class Diff_type, class Accessor, class VALUETYPE>
    00230 inline void initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> multiArray,
    00231                                   int border_width, VALUETYPE v)
    00232 {
    00233     initMultiArrayBorder(multiArray.first, multiArray.second, multiArray.third, border_width, v);
    00234 }
    00235
    00236
    00237 /********************************************************/
    00238 /*                                                      */
    00239 /*                    copyMultiArray                    */
    00240 /*                                                      */
    00241 /********************************************************/
    00242
    00243 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00244           class DestIterator, class DestShape, class DestAccessor>
    00245 void
    00246 copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00247                DestIterator d, DestShape const & dshape, DestAccessor dest, MetaInt<0>)
    00248 {
    00249     if(sshape[0] == 1)
    00250     {
    00251         initLine(d, d + dshape[0], dest, src(s));
    00252     }
    00253     else
    00254     {
    00255         copyLine(s, s + sshape[0], src, d, dest);
    00256     }
    00257 }
    00258
    00259 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00260           class DestIterator, class DestShape, class DestAccessor, int N>
    00261 void
    00262 copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00263                    DestIterator d, DestShape const & dshape, DestAccessor dest, MetaInt<N>)
    00264 {
    00265     DestIterator dend = d + dshape[N];
    00266     if(sshape[N] == 1)
    00267     {
    00268         for(; d < dend; ++d)
    00269         {
    00270             copyMultiArrayImpl(s.begin(), sshape, src, d.begin(), dshape, dest, MetaInt<N-1>());
    00271         }
    00272     }
    00273     else
    00274     {
    00275         for(; d < dend; ++s, ++d)
    00276         {
    00277             copyMultiArrayImpl(s.begin(), sshape, src, d.begin(), dshape, dest, MetaInt<N-1>());
    00278         }
    00279     }
    00280 }
    00281
    00282 /** \brief Copy a multi-dimensional array.
    00283
    00284     This function can be applied in two modes:
    00285
    00286     <DL>
    00287     <DT><b>Standard Mode:</b>
    00288         <DD>If the source and destination arrays have the same size,
    00289         the corresponding array elements are simply copied.
    00290         If necessary, type conversion takes place.
    00291     <DT><b>Expanding Mode:</b>
    00292         <DD>If the source array has length 1 along some (or even all) dimensions,
    00293         the source value at index 0 is used for all destination
    00294         elements in those dimensions. For example, if we have single row of data
    00295         (column length is 1), we can copy it into a 2D image of the same width:
    00296         The given row is automatically repeated for every row of the destination image.
    00297         Again, type conversion os performed if necessary.
    00298     </DL>
    00299
    00300     The arrays must be represented by
    00301     iterators compatible with \ref vigra::MultiIterator, and the iteration range
    00302     is specified by means of shape objects. If only the source shape is given
    00303     the destination array is assumed to have the same shape, and standard mode
    00304     is applied. If two shapes are given, the size of corresponding dimensions
    00305     must be either equal (standard copy), or the source length must be 1
    00306     (expanding copy). The function uses accessors to access the data elements.
    00307
    00308     <b> Declarations:</b>
    00309
    00310     <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
    00311     Namespace: vigra
    00312
    00313     pass arguments explicitly:
    00314     \code
    00315     namespace vigra {
    00316         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00317                   class DestIterator, class DestAccessor>
    00318         void
    00319         copyMultiArray(SrcIterator s,
    00320                        SrcShape const & shape, SrcAccessor src,
    00321                        DestIterator d, DestAccessor dest);
    00322
    00323
    00324         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00325                   class DestIterator, class DestShape, class DestAccessor>
    00326         void
    00327         copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00328                        DestIterator d, DestShape const & dshape, DestAccessor dest);
    00329     }
    00330     \endcode
    00331
    00332
    00333     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00334     \code
    00335     namespace vigra {
    00336         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00337                   class DestIterator, class DestAccessor>
    00338         void
    00339         copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00340                        pair<DestIterator, DestAccessor> const & dest);
    00341
    00342
    00343         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00344                   class DestIterator, class DestShape, class DestAccessor>
    00345         void
    00346         copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00347                        triple<DestIterator, DestShape, DestAccessor> const & dest);
    00348     }
    00349     \endcode
    00350
    00351     <b> Usage - Standard Mode:</b>
    00352
    00353     \code
    00354     typedef vigra::MultiArray<3, int> Array;
    00355     Array src(Array::size_type(100, 200, 50)),
    00356           dest(Array::size_type(100, 200, 50));
    00357     ...
    00358
    00359     vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArray(dest));
    00360     \endcode
    00361
    00362     <b> Usage - Expanding Mode:</b>
    00363
    00364     The source array is only 2D (it has depth 1). Thus, the destination
    00365     will contain 50 identical copies of this image. Note that the destination shape
    00366     must be passed to the algorithm for the expansion to work, so we use
    00367     <tt>destMultiArrayRange()</tt> rather than <tt>destMultiArray()</tt>.
    00368
    00369     \code
    00370     typedef vigra::MultiArray<3, int> Array;
    00371     Array src(Array::size_type(100, 200, 1)),
    00372           dest(Array::size_type(100, 200, 50));
    00373     ...
    00374
    00375     vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArrayRange(dest));
    00376     \endcode
    00377
    00378     <b> Required Interface:</b>
    00379
    00380     \code
    00381     MultiIterator src_begin, dest_begin;
    00382
    00383     SrcAccessor src_accessor;
    00384     DestAccessor dest_accessor;
    00385
    00386     dest_accessor.set(src_accessor(src_begin), dest_begin);
    00387
    00388     \endcode
    00389
    00390 */
    00391 doxygen_overloaded_function(template <...> void copyMultiArray)
    00392
    00393 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00394           class DestIterator, class DestAccessor>
    00395 inline void
    00396 copyMultiArray(SrcIterator s,
    00397                SrcShape const & shape, SrcAccessor src,
    00398                DestIterator d, DestAccessor dest)
    00399 {
    00400     copyMultiArrayImpl(s, shape, src, d, shape, dest, MetaInt<SrcIterator::level>());
    00401 }
    00402
    00403 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00404           class DestIterator, class DestAccessor>
    00405 inline void
    00406 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00407                pair<DestIterator, DestAccessor> const & dest)
    00408 {
    00409
    00410     copyMultiArray(src.first, src.second, src.third, dest.first, dest.second);
    00411 }
    00412
    00413 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00414           class DestIterator, class DestShape, class DestAccessor>
    00415 void
    00416 copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00417                DestIterator d, DestShape const & dshape, DestAccessor dest)
    00418 {
    00419     vigra_precondition(sshape.size() == dshape.size(),
    00420         "copyMultiArray(): dimensionality of source and destination array differ");
    00421     for(unsigned int i=0; i<sshape.size(); ++i)
    00422         vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i],
    00423             "copyMultiArray(): mismatch between source and destination shapes:\n"
    00424             "length of each source dimension must either be 1 or equal to the corresponding "
    00425             "destination length.");
    00426     copyMultiArrayImpl(s, sshape, src, d, dshape, dest, MetaInt<SrcIterator::level>());
    00427 }
    00428
    00429 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00430           class DestIterator, class DestShape, class DestAccessor>
    00431 inline void
    00432 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00433                triple<DestIterator, DestShape, DestAccessor> const & dest)
    00434 {
    00435
    00436     copyMultiArray(src.first, src.second, src.third, dest.first, dest.second, dest.third);
    00437 }
    00438
    00439 /********************************************************/
    00440 /*                                                      */
    00441 /*                 transformMultiArray                  */
    00442 /*                                                      */
    00443 /********************************************************/
    00444
    00445 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00446           class DestIterator, class DestShape, class DestAccessor,
    00447           class Functor>
    00448 void
    00449 transformMultiArrayReduceImpl(SrcIterator s, SrcShape const &, SrcAccessor src,
    00450                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00451                SrcShape const & reduceShape,
    00452                Functor const & ff, MetaInt<0>)
    00453 {
    00454     DestIterator dend = d + dshape[0];
    00455     for(; d < dend; ++s.template dim<0>(), ++d)
    00456     {
    00457         Functor f = ff;
    00458         inspectMultiArray(s, reduceShape, src, f);
    00459         dest.set(f(), d);
    00460     }
    00461 }
    00462
    00463 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00464           class DestIterator, class DestShape, class DestAccessor,
    00465           class Functor, int N>
    00466 void
    00467 transformMultiArrayReduceImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00468                    DestIterator d, DestShape const & dshape, DestAccessor dest,
    00469                    SrcShape const & reduceShape,
    00470                    Functor const & f, MetaInt<N>)
    00471 {
    00472     DestIterator dend = d + dshape[N];
    00473     for(; d < dend; ++s.template dim<N>(), ++d)
    00474     {
    00475         transformMultiArrayReduceImpl(s, sshape, src, d.begin(), dshape, dest,
    00476                                       reduceShape, f, MetaInt<N-1>());
    00477     }
    00478 }
    00479
    00480 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00481           class DestIterator, class DestShape, class DestAccessor,
    00482           class Functor>
    00483 void
    00484 transformMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00485                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00486                Functor const & f, VigraTrueType)
    00487 {
    00488     // reduce mode
    00489     SrcShape reduceShape = sshape;
    00490     for(unsigned int i=0; i<dshape.size(); ++i)
    00491     {
    00492         vigra_precondition(dshape[i] == 1 || sshape[i] == dshape[i],
    00493             "transformMultiArray(): mismatch between source and destination shapes:\n"
    00494             "In 'reduce'-mode, the length of each destination dimension must either be 1\n"
    00495             "or equal to the corresponding source length.");
    00496         if(dshape[i] != 1)
    00497             reduceShape[i] = 1;
    00498     }
    00499     transformMultiArrayReduceImpl(s, sshape, src, d, dshape, dest, reduceShape,
    00500                                   f, MetaInt<SrcIterator::level>());
    00501 }
    00502
    00503 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00504           class DestIterator, class DestShape, class DestAccessor,
    00505           class Functor>
    00506 void
    00507 transformMultiArrayExpandImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00508                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00509                Functor const & f, MetaInt<0>)
    00510 {
    00511     if(sshape[0] == 1)
    00512     {
    00513         initLine(d, d + dshape[0], dest, f(src(s)));
    00514     }
    00515     else
    00516     {
    00517         transformLine(s, s + sshape[0], src, d, dest, f);
    00518     }
    00519 }
    00520
    00521 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00522           class DestIterator, class DestShape, class DestAccessor,
    00523           class Functor, int N>
    00524 void
    00525 transformMultiArrayExpandImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00526                    DestIterator d, DestShape const & dshape, DestAccessor dest,
    00527                    Functor const & f, MetaInt<N>)
    00528 {
    00529     DestIterator dend = d + dshape[N];
    00530     if(sshape[N] == 1)
    00531     {
    00532         for(; d < dend; ++d)
    00533         {
    00534             transformMultiArrayExpandImpl(s.begin(), sshape, src, d.begin(), dshape, dest,
    00535                                           f, MetaInt<N-1>());
    00536         }
    00537     }
    00538     else
    00539     {
    00540         for(; d < dend; ++s, ++d)
    00541         {
    00542             transformMultiArrayExpandImpl(s.begin(), sshape, src, d.begin(), dshape, dest,
    00543                                           f, MetaInt<N-1>());
    00544         }
    00545     }
    00546 }
    00547
    00548 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00549           class DestIterator, class DestShape, class DestAccessor,
    00550           class Functor>
    00551 void
    00552 transformMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00553                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00554                Functor const & f, VigraFalseType)
    00555 {
    00556     // expand mode
    00557     for(unsigned int i=0; i<sshape.size(); ++i)
    00558         vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i],
    00559             "transformMultiArray(): mismatch between source and destination shapes:\n"
    00560             "In 'expand'-mode, the length of each source dimension must either be 1\n"
    00561             "or equal to the corresponding destination length.");
    00562     transformMultiArrayExpandImpl(s, sshape, src, d, dshape, dest,
    00563                                   f, MetaInt<SrcIterator::level>());
    00564 }
    00565
    00566 /** \brief Transform a multi-dimensional array with a unary function or functor.
    00567
    00568     This function can be applied in three modes:
    00569
    00570     <DL>
    00571     <DT><b>Standard Mode:</b>
    00572         <DD>If the source and destination arrays have the same size,
    00573         the transformation given by the functor is applied to every source
    00574         element and the result written into the corresponding destination element.
    00575         Unary functions, unary functors from the STL and the functors specifically
    00576         defined in \ref TransformFunctor can be used in standard mode.
    00577         Creation of new functors is easiest by using \ref FunctorExpressions.
    00578     <DT><b>Expanding Mode:</b>
    00579         <DD>If the source array has length 1 along some (or even all) dimensions,
    00580         the source value at index 0 is used for all destination
    00581         elements in those dimensions. In other words, the source index is not
    00582         incremented along these dimensions, but the transformation functor
    00583         is applied as usual. So, we can expand a small array (e.g. a single row of data,
    00584         column length is 1), into a larger one (e.g. a 2D image with the same width):
    00585         the given values are simply reused as necessary (e.g. for every row of the
    00586         destination image). The same functors as in standard mode can be applied.
    00587     <DT><b>Reducing Mode:</b>
    00588         <DD>If the destination array has length 1 along some (or even all) dimensions,
    00589         the source values in these dimensions are reduced to single values by means
    00590         of a suitable functor (e.g. \ref vigra::ReduceFunctor), which supports two
    00591         function call operators: one
    00592         with a single argument to collect the values, and without argument to
    00593         obtain the final (reduced) result. This behavior is a multi-dimensional
    00594         generalization of the C++ standard function <tt>std::accumulate()</tt>.
    00595     </DL>
    00596
    00597     The arrays must be represented by
    00598     iterators compatible with \ref vigra::MultiIterator, and the iteration range
    00599     is specified by means of shape objects. If only the source shape is given
    00600     the destination array is assumed to have the same shape, and standard mode
    00601     is applied. If two shapes are given, the size of corresponding dimensions
    00602     must be either equal (standard copy), or the source length must be 1
    00603     (expand mode), or the destination length must be 1 (reduce mode). However,
    00604     reduction and expansion cannot be executed at the same time, so the latter
    00605     conditions are mutual exclusive, even if they apply to different dimensions.
    00606
    00607     The function uses accessors to access the data elements.
    00608
    00609     <b> Declarations:</b>
    00610
    00611     <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
    00612     Namespace: vigra
    00613
    00614     pass arguments explicitly:
    00615     \code
    00616     namespace vigra {
    00617         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00618                   class DestIterator, class DestAccessor,
    00619                   class Functor>
    00620         void
    00621         transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00622                             DestIterator d, DestAccessor dest, Functor const & f);
    00623
    00624
    00625         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00626                   class DestIterator, class DestShape, class DestAccessor,
    00627                   class Functor>
    00628         void
    00629         transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00630                             DestIterator d, DestShape const & dshape, DestAccessor dest,
    00631                             Functor const & f);
    00632     }
    00633     \endcode
    00634
    00635
    00636     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00637     \code
    00638     namespace vigra {
    00639         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00640                   class DestIterator, class DestAccessor,
    00641                   class Functor>
    00642         void
    00643         transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00644                             pair<DestIterator, DestAccessor> const & dest, Functor const & f);
    00645
    00646
    00647         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00648                   class DestIterator, class DestShape, class DestAccessor,
    00649                   class Functor>
    00650         void
    00651         transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00652                             triple<DestIterator, DestShape, DestAccessor> const & dest,
    00653                             Functor const & f)
    00654     }
    00655     \endcode
    00656
    00657     <b> Usage - Standard Mode:</b>
    00658
    00659     Source and destination array have the same size.
    00660
    00661     \code
    00662     #include <cmath>         // for sqrt()
    00663
    00664     typedef vigra::MultiArray<3, float> Array;
    00665     Array src(Array::size_type(100, 200, 50)),
    00666           dest(Array::size_type(100, 200, 50));
    00667     ...
    00668
    00669     vigra::transformMultiArray(srcMultiArrayRange(src),
    00670                                destMultiArray(dest),
    00671                                (float(*)(float))&std::sqrt );
    00672
    00673     \endcode
    00674
    00675     <b> Usage - Expand Mode:</b>
    00676
    00677     The source array is only 2D (it has depth 1). Thus, the destination
    00678     will contain 50 identical copies of the transformed source array.
    00679     Note that the destination shape must be passed to the algorithm for
    00680     the expansion to work, so we use <tt>destMultiArrayRange()</tt>
    00681     rather than <tt>destMultiArray()</tt>.
    00682
    00683     \code
    00684     #include <cmath>         // for sqrt()
    00685
    00686     typedef vigra::MultiArray<3, float> Array;
    00687     Array src(Array::size_type(100, 200, 1)),
    00688           dest(Array::size_type(100, 200, 50));
    00689     ...
    00690
    00691     vigra::transformMultiArray(srcMultiArrayRange(src),
    00692                                destMultiArrayRange(dest),
    00693                                (float(*)(float))&std::sqrt );
    00694
    00695     \endcode
    00696
    00697     <b> Usage - Reduce Mode:</b>
    00698
    00699     The destination array is only 1D (it's width and height are 1).
    00700     Thus, it will contain accumulated data for every slice of the source volume
    00701     (or for every frame, if the source is interpreted as an image sequence).
    00702     In the example, we use the functor \ref vigra::FindAverage to calculate
    00703     the average gray value of every slice. Note that the destination shape
    00704     must also be passed for the reduction to work, so we use
    00705     <tt>destMultiArrayRange()</tt> rather than <tt>destMultiArray()</tt>.
    00706
    00707     \code
    00708     typedef vigra::MultiArray<3, float> Array;
    00709     Array src(Array::size_type(100, 200, 50)),
    00710           dest(Array::size_type(1, 1, 50));
    00711     ...
    00712
    00713     vigra::transformMultiArray(srcMultiArrayRange(src),
    00714                                destMultiArrayRange(dest),
    00715                                vigra::FindAverage<float>() );
    00716
    00717     \endcode
    00718
    00719     Note that the functor must define the appropriate traits described below in order to be
    00720     recognized as a reduce functor. This is most easily achieved by deriving from
    00721     <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
    00722
    00723     <b> Required Interface:</b>
    00724
    00725     In standard and expand mode, the functor must be a model of UnaryFunction
    00726     (i.e. support function call with one argument and a return value
    00727     <tt>res = functor(arg)</tt>):
    00728
    00729     \code
    00730     MultiIterator src_begin, src_end, dest_begin;
    00731
    00732     SrcAccessor src_accessor;
    00733     DestAccessor dest_accessor;
    00734     Functor functor;
    00735
    00736     dest_accessor.set(functor(src_accessor(src_begin)), dest_begin);
    00737     \endcode
    00738
    00739     In reduce mode, it must be a model of UnaryAnalyser (i.e. support function call
    00740     with one argument and no return value <tt>functor(arg)</tt>) and Initializer
    00741     (i.e. support function call with no argument, but return value
    00742     <tt>res = functor()</tt>). Internally, such functors are recognized by the
    00743     meta functions <tt>FunctorTraits<FUNCTOR>::isUnaryAnalyser</tt> and
    00744     <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield
    00745     <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
    00746     <tt>FunctorTraits</tt> because otherwise reduce mode will not work.
    00747     This is most easily achieved by deriving the functor from
    00748     <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
    00749     In addition, the functor must be copy constructible in order to start each reduction
    00750     with a fresh functor.
    00751
    00752     \code
    00753     MultiIterator src_begin, src_end, dest_begin;
    00754
    00755     SrcAccessor src_accessor;
    00756     DestAccessor dest_accessor;
    00757
    00758     FUNCTOR initial_functor, functor(initial_functor);
    00759     assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    00760     assert(typeid(FunctorTraits<FUNCTOR>::isUnaryAnalyser) == typeid(VigraTrueType));
    00761
    00762     functor(src_accessor(src_begin));
    00763     dest_accessor.set(functor(), dest_begin);
    00764     \endcode
    00765
    00766 */
    00767 doxygen_overloaded_function(template <...> void transformMultiArray)
    00768
    00769 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00770           class DestIterator, class DestAccessor,
    00771           class Functor>
    00772 inline void
    00773 transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00774                     DestIterator d, DestAccessor dest, Functor const & f)
    00775 {
    00776     transformMultiArrayExpandImpl(s, shape, src, d, shape, dest,
    00777                                   f, MetaInt<SrcIterator::level>());
    00778 }
    00779
    00780 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00781           class DestIterator, class DestAccessor,
    00782           class Functor>
    00783 inline void
    00784 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00785                pair<DestIterator, DestAccessor> const & dest, Functor const & f)
    00786 {
    00787
    00788     transformMultiArray(src.first, src.second, src.third,
    00789                         dest.first, dest.second, f);
    00790 }
    00791
    00792 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00793           class DestIterator, class DestShape, class DestAccessor,
    00794           class Functor>
    00795 void
    00796 transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00797                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00798                Functor const & f)
    00799 {
    00800     vigra_precondition(sshape.size() == dshape.size(),
    00801         "transformMultiArray(): dimensionality of source and destination array differ");
    00802     typedef FunctorTraits<Functor> FT;
    00803     typedef typename
    00804         And<typename FT::isInitializer, typename FT::isUnaryAnalyser>::result
    00805         isAnalyserInitializer;
    00806     transformMultiArrayImpl(s, sshape, src, d, dshape, dest,
    00807                             f, isAnalyserInitializer());
    00808 }
    00809
    00810 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00811           class DestIterator, class DestShape, class DestAccessor,
    00812           class Functor>
    00813 inline void
    00814 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00815                triple<DestIterator, DestShape, DestAccessor> const & dest,
    00816                Functor const & f)
    00817 {
    00818     transformMultiArray(src.first, src.second, src.third,
    00819                         dest.first, dest.second, dest.third, f);
    00820 }
    00821
    00822 /********************************************************/
    00823 /*                                                      */
    00824 /*                combineTwoMultiArrays                 */
    00825 /*                                                      */
    00826 /********************************************************/
    00827
    00828 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    00829           class SrcIterator2, class SrcAccessor2,
    00830           class DestIterator, class DestShape, class DestAccessor,
    00831           class Functor>
    00832 void
    00833 combineTwoMultiArraysReduceImpl(
    00834                SrcIterator1 s1, SrcShape const & , SrcAccessor1 src1,
    00835                SrcIterator2 s2, SrcAccessor2 src2,
    00836                DestIterator d,  DestShape const & dshape, DestAccessor dest,
    00837                SrcShape const & reduceShape,
    00838                Functor const & ff, MetaInt<0>)
    00839 {
    00840     DestIterator dend = d + dshape[0];
    00841     for(; d < dend; ++s1.template dim<0>(), ++s2.template dim<0>(), ++d)
    00842     {
    00843         Functor f = ff;
    00844         inspectTwoMultiArrays(s1, reduceShape, src1, s2, src2, f);
    00845         dest.set(f(), d);
    00846     }
    00847 }
    00848
    00849 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    00850           class SrcIterator2, class SrcAccessor2,
    00851           class DestIterator, class DestShape, class DestAccessor,
    00852           class Functor, int N>
    00853 void
    00854 combineTwoMultiArraysReduceImpl(
    00855                SrcIterator1 s1, SrcShape const & sshape, SrcAccessor1 src1,
    00856                SrcIterator2 s2, SrcAccessor2 src2,
    00857                DestIterator d,  DestShape const & dshape, DestAccessor dest,
    00858                SrcShape const & reduceShape,
    00859                Functor const & f, MetaInt<N>)
    00860 {
    00861     DestIterator dend = d + dshape[N];
    00862     for(; d < dend; ++s1.template dim<N>(), ++s2.template dim<N>(), ++d)
    00863     {
    00864         combineTwoMultiArraysReduceImpl(s1, sshape, src1, s2, src2,
    00865                                         d.begin(), dshape, dest,
    00866                                         reduceShape, f, MetaInt<N-1>());
    00867     }
    00868 }
    00869
    00870 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00871           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00872           class DestIterator, class DestShape, class DestAccessor,
    00873           class Functor>
    00874 void
    00875 combineTwoMultiArraysImpl(
    00876                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00877                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00878                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00879                Functor const & f, VigraTrueType)
    00880 {
    00881     // reduce mode
    00882     SrcShape1 reduceShape = sshape1;
    00883     for(unsigned int i=0; i<dshape.size(); ++i)
    00884     {
    00885         vigra_precondition(sshape1[i] == sshape2[i] &&
    00886                            (dshape[i] == 1 || sshape1[i] == dshape[i]),
    00887             "combineTwoMultiArrays(): mismatch between source and destination shapes:\n"
    00888             "In 'reduce'-mode, the two source shapes must be equal, and\n"
    00889             "the length of each destination dimension must either be 1\n"
    00890             "or equal to the corresponding source length.");
    00891         if(dshape[i] != 1)
    00892             reduceShape[i] = 1;
    00893     }
    00894     combineTwoMultiArraysReduceImpl(s1, sshape1, src1, s2, src2,
    00895                                     d, dshape, dest, reduceShape,
    00896                                     f, MetaInt<SrcIterator1::level>());
    00897 }
    00898
    00899 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00900           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00901           class DestIterator, class DestShape, class DestAccessor,
    00902           class Functor>
    00903 void
    00904 combineTwoMultiArraysExpandImpl(
    00905                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00906                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00907                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00908                Functor const & f, MetaInt<0>)
    00909 {
    00910     DestIterator dend = d + dshape[0];
    00911     if(sshape1[0] == 1 && sshape2[0] == 1)
    00912     {
    00913         initLine(d, dend, dest, f(src1(s1), src2(s2)));
    00914     }
    00915     else if(sshape1[0] == 1)
    00916     {
    00917         typename SrcAccessor1::value_type sv1 = src1(s1);
    00918         for(; d < dend; ++d, ++s2)
    00919             dest.set(f(sv1, src2(s2)), d);
    00920     }
    00921     else if(sshape2[0] == 1)
    00922     {
    00923         typename SrcAccessor2::value_type sv2 = src2(s2);
    00924         for(; d < dend; ++d, ++s1)
    00925             dest.set(f(src1(s1), sv2), d);
    00926     }
    00927     else
    00928     {
    00929         combineTwoLines(s1, s1 + sshape1[0], src1, s2, src2, d, dest, f);
    00930     }
    00931 }
    00932
    00933 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00934           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00935           class DestIterator, class DestShape, class DestAccessor,
    00936           class Functor, int N>
    00937 void
    00938 combineTwoMultiArraysExpandImpl(
    00939                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00940                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00941                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00942                Functor const & f, MetaInt<N>)
    00943 {
    00944     DestIterator dend = d + dshape[N];
    00945     int s1inc = sshape1[N] == 1
    00946                     ? 0
    00947                     : 1;
    00948     int s2inc = sshape2[N] == 1
    00949                     ? 0
    00950                     : 1;
    00951     for(; d < dend; ++d, s1 += s1inc, s2 += s2inc)
    00952     {
    00953         combineTwoMultiArraysExpandImpl(s1.begin(), sshape1, src1,
    00954                                         s2.begin(), sshape2, src2,
    00955                                         d.begin(), dshape, dest,
    00956                                         f, MetaInt<N-1>());
    00957     }
    00958 }
    00959
    00960 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00961           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00962           class DestIterator, class DestShape, class DestAccessor,
    00963           class Functor>
    00964 void
    00965 combineTwoMultiArraysImpl(
    00966                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00967                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00968                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00969                Functor const & f, VigraFalseType)
    00970 {
    00971     // expand mode
    00972     for(unsigned int i=0; i<sshape1.size(); ++i)
    00973         vigra_precondition((sshape1[i] == 1 || sshape1[i] == dshape[i]) &&
    00974                            (sshape2[i] == 1 || sshape2[i] == dshape[i]),
    00975             "combineTwoMultiArrays(): mismatch between source and destination shapes:\n"
    00976             "In 'expand'-mode, the length of each source dimension must either be 1\n"
    00977             "or equal to the corresponding destination length.");
    00978     combineTwoMultiArraysExpandImpl(s1, sshape1, src1, s2, sshape2, src2,
    00979                                     d, dshape, dest,
    00980                                     f, MetaInt<SrcIterator1::level>());
    00981 }
    00982
    00983 /** \brief Combine two multi-dimensional arrays into one using a binary function or functor.
    00984
    00985     This function can be applied in three modes:
    00986
    00987     <DL>
    00988     <DT><b>Standard Mode:</b>
    00989         <DD>If the source and destination arrays have the same size,
    00990         the transformation given by the functor is applied to every pair of
    00991         corresponding source elements and the result written into the corresponding
    00992         destination element.
    00993         Binary functions, binary functors from the STL and the functors specifically
    00994         defined in \ref CombineFunctor can be used in standard mode.
    00995         Creation of new functors is easiest by using \ref FunctorExpressions.
    00996     <DT><b>Expanding Mode:</b>
    00997         <DD>If the source arrays have length 1 along some (or even all) dimensions,
    00998         the source values at index 0 are used for all destination
    00999         elements in those dimensions. In other words, the source index is not
    01000         incremented along those dimensions, but the transformation functor
    01001         is applied as usual. So, we can expand small arrays (e.g. a single row of data,
    01002         column length is 1), into larger ones (e.g. a 2D image with the same width):
    01003         the given values are simply reused as necessary (e.g. for every row of the
    01004         destination image). It is not even necessary that the source array shapes
    01005         are equal. For example, we can combine a small array with one that
    01006         hase the same size as the destination array.
    01007         The same functors as in standard mode can be applied.
    01008     <DT><b>Reducing Mode:</b>
    01009         <DD>If the destination array has length 1 along some (or even all) dimensions,
    01010         the source values in these dimensions are reduced to single values by means
    01011         of a suitable functor which supports two function call operators: one
    01012         with two arguments to collect the values, and one without argument to
    01013         obtain the final (reduced) result. This behavior is a multi-dimensional
    01014         generalization of the C++ standard function <tt>std::accumulate()</tt>.
    01015     </DL>
    01016
    01017     The arrays must be represented by
    01018     iterators compatible with \ref vigra::MultiIterator, and the iteration range
    01019     is specified by means of shape objects. If only a single source shape is given
    01020     the destination array is assumed to have the same shape, and standard mode
    01021     is applied. If three shapes are given, the size of corresponding dimensions
    01022     must be either equal (standard copy), or the length of this dimension must
    01023     be 1 in one or both source arrays
    01024     (expand mode), or the destination length must be 1 (reduce mode). However,
    01025     reduction and expansion cannot be executed at the same time, so the latter
    01026     conditions are mutual exclusive, even if they apply to different dimensions.
    01027
    01028     The function uses accessors to access the data elements.
    01029
    01030     <b> Declarations:</b>
    01031
    01032     <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
    01033     Namespace: vigra
    01034
    01035     pass arguments explicitly:
    01036     \code
    01037     namespace vigra {
    01038         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01039                   class SrcIterator2, class SrcAccessor2,
    01040                   class DestIterator, class DestAccessor,
    01041                   class Functor>
    01042         void combineTwoMultiArrays(
    01043                        SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01044                        SrcIterator2 s2, SrcAccessor2 src2,
    01045                        DestIterator d, DestAccessor dest, Functor const & f);
    01046
    01047
    01048         template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    01049                   class SrcIterator2, class SrcShape2, class SrcAccessor2,
    01050                   class DestIterator, class DestShape, class DestAccessor,
    01051                   class Functor>
    01052         void combineTwoMultiArrays(
    01053                        SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    01054                        SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    01055                        DestIterator d, DestShape const & dshape, DestAccessor dest,
    01056                        Functor const & f);
    01057             }
    01058     \endcode
    01059
    01060
    01061     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01062     \code
    01063     namespace vigra {
    01064         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01065                   class SrcIterator2, class SrcAccessor2,
    01066                   class DestIterator, class DestAccessor, class Functor>
    01067         void combineTwoMultiArrays(
    01068                        triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    01069                        pair<SrcIterator2, SrcAccessor2> const & src2,
    01070                        pair<DestIterator, DestAccessor> const & dest, Functor const & f);
    01071
    01072
    01073         template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    01074                   class SrcIterator2, class SrcShape2, class SrcAccessor2,
    01075                   class DestIterator, class DestShape, class DestAccessor,
    01076                   class Functor>
    01077         void combineTwoMultiArrays(
    01078                        triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1,
    01079                        triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2,
    01080                        triple<DestIterator, DestShape, DestAccessor> const & dest,
    01081                        Functor const & f);
    01082     }
    01083     \endcode
    01084
    01085     <b> Usage - Standard Mode:</b>
    01086
    01087     Source and destination arrays have the same size.
    01088
    01089     \code
    01090     #include <functional>     // for std::plus
    01091
    01092     typedef vigra::MultiArray<3, int> Array;
    01093     Array src1(Array::size_type(100, 200, 50)),
    01094           src2(Array::size_type(100, 200, 50)),
    01095           dest(Array::size_type(100, 200, 50));
    01096     ...
    01097
    01098     vigra::combineTwoMultiArrays(
    01099                 srcMultiArrayRange(src1),
    01100                 srcMultiArray(src2),
    01101                 destMultiArray(dest),
    01102                 std::plus<int>());
    01103
    01104     \endcode
    01105
    01106     <b> Usage - Expand Mode:</b>
    01107
    01108     One source array is only 2D (it has depth 1). This image will be added
    01109     to every slice of the other source array, and the result
    01110     if written into the corresponding destination slice. Note that the shapes
    01111     of all arrays must be passed to the algorithm, so we use
    01112     <tt>srcMultiArrayRange()</tt> and <tt>destMultiArrayRange()</tt>
    01113     rather than <tt>srcMultiArray()</tt> and <tt>destMultiArray()</tt>.
    01114
    01115     \code
    01116     #include <functional>     // for std::plus
    01117
    01118     typedef vigra::MultiArray<3, int> Array;
    01119     Array src1(Array::size_type(100, 200, 1)),
    01120           src2(Array::size_type(100, 200, 50)),
    01121           dest(Array::size_type(100, 200, 50));
    01122     ...
    01123
    01124     vigra::combineTwoMultiArrays(
    01125                 srcMultiArrayRange(src1),
    01126                 srcMultiArray(src2),
    01127                 destMultiArray(dest),
    01128                 std::plus<int>());
    01129
    01130     \endcode
    01131
    01132     <b> Usage - Reduce Mode:</b>
    01133
    01134     The destination array is only 1D (it's width and height are 1).
    01135     Thus, it will contain accumulated data for every slice of the source volumes
    01136     (or for every frame, if the sources are interpreted as image sequences).
    01137     In the example, we use \ref vigra::ReduceFunctor together with a functor
    01138     expression (see \ref FunctorExpressions)
    01139     to calculate the total absolute difference of the gray values in every pair of
    01140     source slices. Note that the shapes of all arrays must be passed
    01141     to the algorithm in order for the reduction to work, so we use
    01142     <tt>srcMultiArrayRange()</tt> and <tt>destMultiArrayRange()</tt>
    01143     rather than <tt>srcMultiArray()</tt> and <tt>destMultiArray()</tt>.
    01144
    01145     \code
    01146     #include <vigra/functorexpression.hxx>
    01147     using namespace vigra::functor;
    01148
    01149     typedef vigra::MultiArray<3, int> Array;
    01150     Array src1(Array::size_type(100, 200, 50)),
    01151           src2(Array::size_type(100, 200, 50)),
    01152           dest(Array::size_type(1, 1, 50));
    01153     ...
    01154
    01155     vigra::combineTwoMultiArrays(
    01156                 srcMultiArrayRange(src1),
    01157                 srcMultiArray(src2),
    01158                 destMultiArray(dest),
    01159                 reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) );
    01160                 // Arg1() is the sum accumulated so far, initialized with 0
    01161
    01162     \endcode
    01163
    01164     Note that the functor must define the appropriate traits described below in order to be
    01165     recognized as a reduce functor. This is most easily achieved by deriving from
    01166     <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
    01167
    01168     <b> Required Interface:</b>
    01169
    01170     In standard and expand mode, the functor must be a model of BinaryFunction
    01171     (i.e. support function call with two arguments and a return value
    01172     <tt>res = functor(arg1, arg2)</tt>):
    01173
    01174     \code
    01175     MultiIterator src1_begin, src2_begin, dest_begin;
    01176
    01177     SrcAccessor1 src1_accessor;
    01178     SrcAccessor2 src2_accessor;
    01179     DestAccessor dest_accessor;
    01180
    01181     Functor functor;
    01182
    01183     dest_accessor.set(
    01184           functor(src1_accessor(src1_begin), src2_accessor(src2_begin)),
    01185           dest_begin);
    01186
    01187     \endcode
    01188
    01189     In reduce mode, it must be a model of BinaryAnalyser (i.e. support function call
    01190     with two arguments and no return value <tt>functor(arg1, arg2)</tt>) and Initializer
    01191     (i.e. support function call with no argument, but return value
    01192     <tt>res = functor()</tt>). Internally, such functors are recognized by the
    01193     meta functions <tt>FunctorTraits<FUNCTOR>::isBinaryAnalyser</tt> and
    01194     <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield
    01195     <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
    01196     <tt>FunctorTraits</tt> because otherwise reduce mode will not work.
    01197     This is most easily achieved by deriving the functor from
    01198     <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
    01199     In addition, the functor must be copy constructible in order to start each reduction
    01200     with a fresh functor.
    01201
    01202     \code
    01203     MultiIterator src1_begin, src2_begin, dest_begin;
    01204
    01205     SrcAccessor1 src1_accessor;
    01206     SrcAccessor2 src2_accessor;
    01207     DestAccessor dest_accessor;
    01208
    01209     FUNCTOR initial_functor, functor(initial_functor);
    01210     assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    01211     assert(typeid(FunctorTraits<FUNCTOR>::isBinaryAnalyser) == typeid(VigraTrueType));
    01212
    01213     functor(src1_accessor(src1_begin), src2_accessor(src2_begin));
    01214     dest_accessor.set(functor(), dest_begin);
    01215     \endcode
    01216
    01217 */
    01218 doxygen_overloaded_function(template <...> void combineTwoMultiArrays)
    01219
    01220 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01221           class SrcIterator2, class SrcAccessor2,
    01222           class DestIterator, class DestAccessor,
    01223           class Functor>
    01224 inline void
    01225 combineTwoMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01226                SrcIterator2 s2, SrcAccessor2 src2,
    01227                DestIterator d, DestAccessor dest, Functor const & f)
    01228 {
    01229     combineTwoMultiArraysExpandImpl(s1, shape, src1, s2, shape, src2, d, shape, dest, f,
    01230                                     MetaInt<SrcIterator1::level>());
    01231 }
    01232
    01233 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01234           class SrcIterator2, class SrcAccessor2,
    01235           class DestIterator, class DestAccessor, class Functor>
    01236 inline void
    01237 combineTwoMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    01238                pair<SrcIterator2, SrcAccessor2> const & src2,
    01239                pair<DestIterator, DestAccessor> const & dest, Functor const & f)
    01240 {
    01241
    01242     combineTwoMultiArrays(
    01243            src1.first, src1.second, src1.third,
    01244            src2.first, src2.second, dest.first, dest.second, f);
    01245 }
    01246
    01247 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    01248           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    01249           class DestIterator, class DestShape, class DestAccessor,
    01250           class Functor>
    01251 void
    01252 combineTwoMultiArrays(
    01253                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    01254                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    01255                DestIterator d, DestShape const & dshape, DestAccessor dest,
    01256                Functor const & f)
    01257 {
    01258     vigra_precondition(sshape1.size() == dshape.size() && sshape2.size() == dshape.size(),
    01259         "combineTwoMultiArrays(): dimensionality of source and destination arrays differ");
    01260
    01261     typedef FunctorTraits<Functor> FT;
    01262     typedef typename
    01263         And<typename FT::isInitializer, typename FT::isBinaryAnalyser>::result
    01264         isAnalyserInitializer;
    01265     combineTwoMultiArraysImpl(s1, sshape1, src1, s2, sshape2, src2, d, dshape, dest,
    01266                               f, isAnalyserInitializer());
    01267 }
    01268
    01269 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    01270           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    01271           class DestIterator, class DestShape, class DestAccessor,
    01272           class Functor>
    01273 inline void
    01274 combineTwoMultiArrays(
    01275                triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1,
    01276                triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2,
    01277                triple<DestIterator, DestShape, DestAccessor> const & dest,
    01278                Functor const & f)
    01279 {
    01280     combineTwoMultiArrays(src1.first, src1.second, src1.third,
    01281                           src2.first, src2.second, src2.third,
    01282                           dest.first, dest.second, dest.third, f);
    01283 }
    01284
    01285 /********************************************************/
    01286 /*                                                      */
    01287 /*               combineThreeMultiArrays                */
    01288 /*                                                      */
    01289 /********************************************************/
    01290
    01291 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01292           class SrcIterator2, class SrcAccessor2,
    01293           class SrcIterator3, class SrcAccessor3,
    01294           class DestIterator, class DestAccessor,
    01295           class Functor>
    01296 inline void
    01297 combineThreeMultiArraysImpl(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01298                SrcIterator2 s2, SrcAccessor2 src2,
    01299                SrcIterator3 s3, SrcAccessor3 src3,
    01300                DestIterator d, DestAccessor dest, Functor const & f, MetaInt<0>)
    01301 {
    01302     combineThreeLines(s1, s1 + shape[0], src1, s2, src2, s3, src3, d, dest, f);
    01303 }
    01304
    01305 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01306           class SrcIterator2, class SrcAccessor2,
    01307           class SrcIterator3, class SrcAccessor3,
    01308           class DestIterator, class DestAccessor,
    01309           class Functor, int N>
    01310 void
    01311 combineThreeMultiArraysImpl(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01312                SrcIterator2 s2, SrcAccessor2 src2,
    01313                SrcIterator3 s3, SrcAccessor3 src3,
    01314                DestIterator d, DestAccessor dest,
    01315                    Functor const & f, MetaInt<N>)
    01316 {
    01317     SrcIterator1 s1end = s1 + shape[N];
    01318     for(; s1 < s1end; ++s1, ++s2, ++s3, ++d)
    01319     {
    01320         combineThreeMultiArraysImpl(s1.begin(), shape, src1,
    01321                                   s2.begin(), src2, s3.begin(), src3, d.begin(), dest,
    01322                                   f, MetaInt<N-1>());
    01323     }
    01324 }
    01325
    01326
    01327 /** \brief Combine three multi-dimensional arrays into one using a
    01328            ternary function or functor.
    01329
    01330     Except for the fact that it operates on three input arrays, this function is
    01331     identical to \ref combineTwoMultiArrays().
    01332
    01333     <b> Declarations:</b>
    01334
    01335     pass arguments explicitly:
    01336     \code
    01337     namespace vigra {
    01338         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01339                   class SrcIterator2, class SrcAccessor2,
    01340                   class SrcIterator3, class SrcAccessor3,
    01341                   class DestIterator, class DestAccessor,
    01342                   class Functor>
    01343         void
    01344         combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01345                        SrcIterator2 s2, SrcAccessor2 src2,
    01346                        SrcIterator3 s3, SrcAccessor3 src3,
    01347                        DestIterator d, DestAccessor dest, Functor const & f);
    01348                     }
    01349     \endcode
    01350
    01351
    01352     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01353     \code
    01354     namespace vigra {
    01355         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01356                   class SrcIterator2, class SrcAccessor2,
    01357                   class SrcIterator3, class SrcAccessor3,
    01358                   class DestIterator, class DestAccessor,
    01359                   class Functor>
    01360         inline void
    01361         combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    01362                        pair<SrcIterator2, SrcAccessor2> const & src2,
    01363                        pair<SrcIterator3, SrcAccessor3> const & src3,
    01364                        pair<DestIterator, DestAccessor> const & dest, Functor const & f);
    01365     }
    01366     \endcode
    01367
    01368     <b> Usage:</b>
    01369
    01370     <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
    01371     Namespace: vigra
    01372
    01373     \code
    01374     #include <functional>     // for plus
    01375
    01376     typedef vigra::MultiArray<3, int> Array;
    01377     Array src1(Array::size_type(100, 200, 50)),
    01378           src2(Array::size_type(100, 200, 50)),
    01379           src3(Array::size_type(100, 200, 50)),
    01380           dest(Array::size_type(100, 200, 50));
    01381     ...
    01382
    01383     vigra::combineThreeMultiArrays(
    01384                 srcMultiArrayRange(src1),
    01385                 srcMultiArray(src2),
    01386                 srcMultiArray(src3),
    01387                 destMultiArray(dest),
    01388                 SomeThreeArgumentFunctor());
    01389
    01390     \endcode
    01391 */
    01392 doxygen_overloaded_function(template <...> void combineThreeMultiArrays)
    01393
    01394 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01395           class SrcIterator2, class SrcAccessor2,
    01396           class SrcIterator3, class SrcAccessor3,
    01397           class DestIterator, class DestAccessor,
    01398           class Functor>
    01399 inline void
    01400 combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01401                SrcIterator2 s2, SrcAccessor2 src2,
    01402                SrcIterator3 s3, SrcAccessor3 src3,
    01403                DestIterator d, DestAccessor dest, Functor const & f)
    01404 {
    01405     combineThreeMultiArraysImpl(s1, shape, src1, s2, src2, s3, src3, d, dest, f,
    01406                               MetaInt<SrcIterator1::level>());
    01407 }
    01408
    01409 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01410           class SrcIterator2, class SrcAccessor2,
    01411           class SrcIterator3, class SrcAccessor3,
    01412           class DestIterator, class DestAccessor,
    01413           class Functor>
    01414 inline void
    01415 combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    01416                pair<SrcIterator2, SrcAccessor2> const & src2,
    01417                pair<SrcIterator3, SrcAccessor3> const & src3,
    01418                pair<DestIterator, DestAccessor> const & dest, Functor const & f)
    01419 {
    01420
    01421     combineThreeMultiArrays(
    01422            src1.first, src1.second, src1.third,
    01423            src2.first, src2.second, src3.first, src3.second, dest.first, dest.second, f);
    01424 }
    01425
    01426 /********************************************************/
    01427 /*                                                      */
    01428 /*                  inspectMultiArray                   */
    01429 /*                                                      */
    01430 /********************************************************/
    01431
    01432 template <class Iterator, class Shape, class Accessor, class Functor>
    01433 inline void
    01434 inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,  Functor & f, MetaInt<0>)
    01435 {
    01436     inspectLine(s, s + shape[0], a, f);
    01437 }
    01438
    01439 template <class Iterator, class Shape, class Accessor, class Functor, int N>
    01440 void
    01441 inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,  Functor & f, MetaInt<N>)
    01442 {
    01443     Iterator send = s + shape[N];
    01444     for(; s < send; ++s)
    01445     {
    01446         inspectMultiArrayImpl(s.begin(), shape, a, f, MetaInt<N-1>());
    01447     }
    01448 }
    01449
    01450 /** \brief Call an analyzing functor at every element of a multi-dimensional array.
    01451
    01452     This function can be used to collect statistics of the array etc.
    01453     The results must be stored in the functor, which serves as a return
    01454     value. The arrays must be represented by
    01455     iterators compatible with \ref vigra::MultiIterator.
    01456     The function uses an accessor to access the pixel data. Note that the iterator range
    01457     must be specified by a shape object, because otherwise we could not control
    01458     the range simultaneously in all dimensions (this is a necessary consequence
    01459     of the \ref vigra::MultiIterator design).
    01460
    01461     <b> Declarations:</b>
    01462
    01463     pass arguments explicitly:
    01464     \code
    01465     namespace vigra {
    01466         template <class Iterator, class Shape, class Accessor, class Functor>
    01467         void
    01468         inspectMultiArray(Iterator s, Shape const & shape, Accessor a,  Functor & f);
    01469     }
    01470     \endcode
    01471
    01472     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01473     \code
    01474     namespace vigra {
    01475         template <class Iterator, class Shape, class Accessor, class Functor>
    01476         void
    01477         inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f);
    01478     }
    01479     \endcode
    01480
    01481     <b> Usage:</b>
    01482
    01483     <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
    01484     Namespace: vigra
    01485
    01486     \code
    01487     typedef vigra::MultiArray<3, int> Array;
    01488     Array array(Array::size_type(100, 200, 50));
    01489
    01490     // init functor
    01491     vigra::FindMinMax<int> minmax;
    01492
    01493     vigra::inspectMultiArray(srcMultiArrayRange(array), minmax);
    01494
    01495     cout << "Min: " << minmax.min << " Max: " << minmax.max;
    01496
    01497     \endcode
    01498
    01499     <b> Required Interface:</b>
    01500
    01501     \code
    01502     MultiIterator src_begin;
    01503
    01504     Accessor accessor;
    01505     Functor functor;
    01506
    01507     functor(accessor(src_begin));
    01508     \endcode
    01509
    01510 */
    01511 doxygen_overloaded_function(template <...> void inspectMultiArray)
    01512
    01513 template <class Iterator, class Shape, class Accessor>
    01514 struct inspectMultiArray_binder
    01515 {
    01516     Iterator      s;
    01517     const Shape & shape;
    01518     Accessor      a;
    01519     inspectMultiArray_binder(Iterator s_, const Shape & shape_, Accessor a_)
    01520         : s(s_), shape(shape_), a(a_) {}
    01521     template <class Functor>
    01522     void operator()(Functor & f)
    01523     {
    01524         inspectMultiArrayImpl(s, shape, a, f, MetaInt<Iterator::level>());
    01525     }
    01526 };
    01527
    01528 template <class Iterator, class Shape, class Accessor, class Functor>
    01529 inline void
    01530 inspectMultiArray(Iterator s, Shape const & shape, Accessor a, Functor & f)
    01531 {
    01532     inspectMultiArray_binder<Iterator, Shape, Accessor> g(s, shape, a);
    01533     detail::extra_passes_select(g, f);
    01534 }
    01535
    01536 template <class Iterator, class Shape, class Accessor, class Functor>
    01537 inline void
    01538 inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f)
    01539 {
    01540     inspectMultiArray(s.first, s.second, s.third, f);
    01541 }
    01542
    01543 /********************************************************/
    01544 /*                                                      */
    01545 /*                  inspectTwoMultiArrays               */
    01546 /*                                                      */
    01547 /********************************************************/
    01548
    01549 template <class Iterator1, class Shape, class Accessor1,
    01550           class Iterator2, class Accessor2,
    01551           class Functor>
    01552 inline void
    01553 inspectTwoMultiArraysImpl(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01554                           Iterator2 s2, Accessor2 a2,
    01555                           Functor & f, MetaInt<0>)
    01556 {
    01557     inspectTwoLines(s1, s1 + shape[0], a1, s2, a2, f);
    01558 }
    01559
    01560 template <class Iterator1, class Shape, class Accessor1,
    01561           class Iterator2, class Accessor2,
    01562           class Functor, int N>
    01563 void
    01564 inspectTwoMultiArraysImpl(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01565                           Iterator2 s2, Accessor2 a2,
    01566                           Functor & f, MetaInt<N>)
    01567 {
    01568     Iterator1 s1end = s1 + shape[N];
    01569     for(; s1 < s1end; ++s1, ++s2)
    01570     {
    01571         inspectTwoMultiArraysImpl(s1.begin(), shape, a1,
    01572                                   s2.begin(), a2, f, MetaInt<N-1>());
    01573     }
    01574 }
    01575
    01576 /** \brief Call an analyzing functor at all corresponding elements of
    01577            two multi-dimensional arrays.
    01578
    01579     This function can be used to collect statistics of the array etc.
    01580     The results must be stored in the functor, which serves as a return
    01581     value. The arrays must be represented by
    01582     iterators compatible with \ref vigra::MultiIterator.
    01583     The function uses an accessor to access the pixel data. Note that the iterator range
    01584     must be specified by a shape object, because otherwise we could not control
    01585     the range simultaneously in all dimensions (this is a necessary consequence
    01586     of the \ref vigra::MultiIterator design).
    01587
    01588     <b> Declarations:</b>
    01589
    01590     pass arguments explicitly:
    01591     \code
    01592     namespace vigra {
    01593         template <class Iterator1, class Shape, class Accessor1,
    01594                   class Iterator2, class Accessor2,
    01595                   class Functor>
    01596         void
    01597         inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01598                               Iterator2 s2, Accessor2 a2, Functor & f);
    01599     }
    01600     \endcode
    01601
    01602     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01603     \code
    01604     namespace vigra {
    01605         template <class Iterator1, class Shape1, class Accessor1,
    01606                   class Iterator2, class Accessor2,
    01607                   class Functor>
    01608         void
    01609         inspectTwoMultiArrays(triple<Iterator1, Shape1, Accessor1> const & s1,
    01610                               pair<Iterator2, Accessor2> const & s2, Functor & f);
    01611     }
    01612     \endcode
    01613
    01614     <b> Usage:</b>
    01615
    01616     <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
    01617     Namespace: vigra
    01618
    01619     \code
    01620     typedef vigra::MultiArray<3, int> Array;
    01621     Array array1(Array::size_type(100, 200, 50)),
    01622           array2(Array::size_type(100, 200, 50));
    01623
    01624     // init functor
    01625     SomeStatisticsFunctor stats(..);
    01626
    01627     vigra::inspectTwoMultiArrays(srcMultiArrayRange(array1), srcMultiArray(array2), stats);
    01628
    01629     \endcode
    01630
    01631     <b> Required Interface:</b>
    01632
    01633     \code
    01634     MultiIterator src1_begin, src2_begin;
    01635
    01636     Accessor a1, a2;
    01637     Functor functor;
    01638
    01639     functor(a1(src1_begin), a2(src2_begin));
    01640     \endcode
    01641
    01642 */
    01643 doxygen_overloaded_function(template <...> void inspectTwoMultiArrays)
    01644
    01645 template <class Iterator1, class Shape, class Accessor1,
    01646           class Iterator2, class Accessor2>
    01647 struct inspectTwoMultiArrays_binder
    01648 {
    01649     Iterator1     s1;
    01650     const Shape & shape;
    01651     Accessor1     a1;
    01652     Iterator2     s2;
    01653     Accessor2     a2;
    01654     inspectTwoMultiArrays_binder(Iterator1 s1_, const Shape & shape_,
    01655                                  Accessor1 a1_, Iterator2 s2_, Accessor2 a2_)
    01656         : s1(s1_), shape(shape_), a1(a1_), s2(s2_), a2(a2_) {}
    01657     template <class Functor>
    01658     void operator()(Functor & f)
    01659     {
    01660         inspectTwoMultiArraysImpl(s1, shape, a1, s2, a2, f,
    01661                                   MetaInt<Iterator1::level>());
    01662     }
    01663 };
    01664
    01665 template <class Iterator1, class Shape, class Accessor1,
    01666           class Iterator2, class Accessor2,
    01667           class Functor>
    01668 inline void
    01669 inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01670                       Iterator2 s2, Accessor2 a2, Functor & f)
    01671 {
    01672     inspectTwoMultiArrays_binder<Iterator1, Shape, Accessor1,
    01673                                  Iterator2, Accessor2>
    01674         g(s1, shape, a1, s2, a2);
    01675     detail::extra_passes_select(g, f);
    01676 }
    01677
    01678 template <class Iterator1, class Shape, class Accessor1,
    01679           class Iterator2, class Accessor2,
    01680           class Functor>
    01681 inline
    01682 void
    01683 inspectTwoMultiArrays(triple<Iterator1, Shape, Accessor1> const & s1,
    01684                       pair<Iterator2, Accessor2> const & s2, Functor & f)
    01685 {
    01686     inspectTwoMultiArrays(s1.first, s1.second, s1.third,
    01687                           s2.first, s2.second, f);
    01688 }
    01689
    01690 //@}
    01691
    01692 }  //-- namespace vigra
    01693
    01694
    01695 #endif  //-- VIGRA_MULTI_POINTOPERATORS_H

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.9.0 (Tue Nov 6 2012)