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

details vigra/iteratortraits.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
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 /*    The VIGRA Website is                                              */
00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00010 /*    Please direct questions, bug reports, and contributions to        */
00011 /*        koethe@informatik.uni-hamburg.de          or                  */
00012 /*        vigra@kogs1.informatik.uni-hamburg.de                         */
00013 /*                                                                      */
00014 /*    Permission is hereby granted, free of charge, to any person       */
00015 /*    obtaining a copy of this software and associated documentation    */
00016 /*    files (the "Software"), to deal in the Software without           */
00017 /*    restriction, including without limitation the rights to use,      */
00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00019 /*    sell copies of the Software, and to permit persons to whom the    */
00020 /*    Software is furnished to do so, subject to the following          */
00021 /*    conditions:                                                       */
00022 /*                                                                      */
00023 /*    The above copyright notice and this permission notice shall be    */
00024 /*    included in all copies or substantial portions of the             */
00025 /*    Software.                                                         */
00026 /*                                                                      */
00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00035 /*                                                                      */
00036 /************************************************************************/
00037 
00038 
00039 #ifndef VIGRA_ITERATORTRAITS_HXX
00040 #define VIGRA_ITERATORTRAITS_HXX
00041 
00042 #include <vigra/accessor.hxx>
00043 #include <vigra/imageiteratoradapter.hxx>
00044 
00045 namespace vigra {
00046 
00047 /** \addtogroup ImageIterators
00048 */
00049 //@{
00050 /** \brief Export associated information for each image iterator.
00051 
00052     The IteratorTraits class contains the following fields:
00053 
00054     \code
00055     template <class T>
00056     struct IteratorTraits
00057     {
00058         typedef T                                     Iterator;
00059         typedef Iterator                              iterator;
00060         typedef typename iterator::iterator_category  iterator_category;
00061         typedef typename iterator::value_type         value_type;
00062         typedef typename iterator::reference          reference;
00063         typedef typename iterator::index_reference    index_reference;
00064         typedef typename iterator::pointer            pointer;
00065         typedef typename iterator::difference_type    difference_type;
00066         typedef typename iterator::row_iterator       row_iterator;
00067         typedef typename iterator::column_iterator    column_iterator;
00068         typedef StandardAccessor<value_type>          DefaultAccessor;
00069         typedef StandardAccessor<value_type>          default_accessor;
00070 
00071         typedef VigraTrueType/VigraFalseType          hasConstantStrides;
00072     };
00073     \endcode
00074 
00075     By (partially) specializing this template for an iterator class
00076     the defaults given above can be changed as appropriate. For example, iterators
00077     for rgb images are associated with <TT>RGBAccessor<value_type></TT>
00078     instead of <TT>StandardAccessor<value_type></TT>. To get the accessor
00079     associated with a given iterator, use code like this:
00080 
00081     \code
00082     template <class Iterator>
00083     void foo(Iterator i)
00084     {
00085         typedef typename IteratorTraits<Iterator>::DefaultAccessor Accessor;
00086         Accessor a;
00087         ...
00088     }
00089     \endcode
00090 
00091     This technique is, for example, used by the
00092     \ref IteratorBasedArgumentObjectFactories. The possibility to retrieve the default accessor by means of a traits
00093     class is especially important since this information is not
00094     contained in the iterator directly.
00095     
00096     The member <tt>hasConstantStrides</tt> is useful for certain 
00097     optimizations: it helps to decide whether we can replace iterator
00098     operations such as <tt>iter++</tt> ot <tt>iter =+ n</tt> with
00099     corresponding pointer operations (which may be faster), where
00100     the pointer is obtained as the address of iterator's pointee 
00101     (the object the iterator currently  refers to). 
00102     This flag would be tt>VigraFalseType</tt> for a
00103     <tt>std::list&lt;int&gt;::iterator</tt>, but is <tt>VigraTrueType</tt> 
00104     for most VIGRA iterators.
00105 
00106     <b>\#include</b> "<a href="iteratortraits_8hxx-source.html">vigra/iteratortraits.hxx</a>"
00107     Namespace: vigra
00108 */
00109 template <class T>
00110 struct IteratorTraits
00111 {
00112     typedef T                                          Iterator;
00113     typedef Iterator                                   iterator;
00114     typedef typename iterator::iterator_category       iterator_category;
00115     typedef typename iterator::value_type              value_type;
00116     typedef typename iterator::reference               reference;
00117     typedef typename iterator::index_reference         index_reference;
00118     typedef typename iterator::pointer                 pointer;
00119     typedef typename iterator::difference_type         difference_type;
00120     typedef typename iterator::row_iterator            row_iterator;
00121     typedef typename iterator::column_iterator         column_iterator;
00122     typedef typename
00123         AccessorTraits<value_type>::default_accessor   DefaultAccessor;
00124     typedef DefaultAccessor                            default_accessor;
00125 
00126     // default: disable the constant strides optimization
00127     typedef VigraFalseType                             hasConstantStrides;
00128 };
00129 
00130 template <class T>
00131 struct IteratorTraitsBase
00132 {
00133     typedef T                                     Iterator;
00134     typedef Iterator                              iterator;
00135     typedef typename iterator::iterator_category  iterator_category;
00136     typedef typename iterator::value_type         value_type;
00137     typedef typename iterator::reference          reference;
00138     typedef typename iterator::index_reference    index_reference;
00139     typedef typename iterator::pointer            pointer;
00140     typedef typename iterator::difference_type    difference_type;
00141     typedef typename iterator::row_iterator       row_iterator;
00142     typedef typename iterator::column_iterator    column_iterator;
00143 };
00144 
00145 /***********************************************************/
00146 
00147 /** \page ArgumentObjectFactories Argument Object Factories
00148 
00149     Factory functions to create argument objects which simplify long argument lists.
00150 
00151     <DL>
00152     <DT>
00153         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00154         \ref ImageBasedArgumentObjectFactories
00155         <DD>
00156     <DT>
00157         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00158         \ref MultiArrayBasedArgumentObjectFactories
00159         <DD>
00160     <DT>
00161         <IMG BORDER=0 ALT="-" SRC="documents/bullet.gif">
00162         \ref IteratorBasedArgumentObjectFactories
00163         <DD>
00164     </DL>
00165 
00166     Long argument lists provide for greater flexibility of functions,
00167     but they are also tedious and error prone, when we don't need
00168     the flexibility. Thus, we define argument objects which
00169     automatically provide reasonable defaults for those arguments that we
00170     didn't specify explicitly.
00171 
00172     The argument objects are created via a number of factory functions.
00173     Since these functions have descriptive names, they also serve
00174     to improve readability: the name of each factory tells te purpose of its
00175     argument object.
00176 
00177     Consider the following example. Without argument objects we had to
00178     write something like this (cf. \ref copyImageIf()):
00179 
00180     \code
00181     vigra::BImage img1, img2, img3;
00182 
00183     // fill img1 and img2 ...
00184 
00185     vigra::copyImageIf(img1.upperLeft(), img1.lowerRight(), img1.accessor(),
00186                 img2.upperLeft(), img2.accessor(),
00187                 img3.upperLeft(), img3.accessor());
00188     \endcode
00189 
00190     Using the argument object factories, this becomes much shorter and
00191     more readable:
00192 
00193     \code
00194     vigra::copyImageIf(srcImageRange(img1),
00195                 maskImage(img2),
00196                 destImage(img3));
00197     \endcode
00198 
00199     The names of the factories clearly tell which image is source, mask,
00200     and destination. In addition, the suffix <TT>Range</TT> must be used
00201     for those argument objects that need to specify the lower right
00202     corner of the region of interest. Typically, this is only the first
00203     source argument, but sometimes the first destiniation argument must
00204     also contain a range.
00205 
00206     The factory functions come in two flavours: Iterator based and
00207     image based factories. Above we have seen the image based variant.
00208     The iterator based variant would look like this:
00209 
00210     \code
00211     vigra::copyImageIf(srcIterRange(img1.upperLeft(), img1.lowerRight()),
00212                 maskIter(img2.upperLeft()),
00213                 destIter(img3.upperLeft()));
00214     \endcode
00215 
00216     These factory functions contain the word <TT>Iter</TT> instead of the word
00217     <TT>Image</TT>,  They would normally be used if we couldn't access the
00218     images (for example, within a function which got passed iterators)
00219     or if we didn't want to operate on the entire image. The default
00220     accessor is obtained via \ref vigra::IteratorTraits.
00221 
00222     All factory functions also allow to specify accessors explicitly. This
00223     is useful if we can't use the default accessor. This variant looks
00224     like this:
00225 
00226     \code
00227     vigra::copyImageIf(srcImageRange(img1),
00228                 maskImage(img2, MaskPredicateAccessor()),
00229                 destImage(img3));
00230     \endcode
00231 
00232     or
00233 
00234     \code
00235     vigra::copyImageIf(srcIterRange(img1.upperLeft(), img1.lowerRight()),
00236                 maskIter(img2.upperLeft(), MaskPredicateAccessor()),
00237                 destIter(img3.upperLeft()));
00238     \endcode
00239 
00240     All versions can be mixed freely within one explession.
00241     Technically, the argument objects are simply defined as
00242     pairs and triples of iterators and accessor so that all algorithms
00243     should declare a call interface version based on pairs and triples
00244     (see for example \ref copyImageIf()).
00245 
00246   \section ImageBasedArgumentObjectFactories Image Based Argument Object Factories
00247 
00248     <b>Include:</b> automatically included with the image classes<br>
00249     Namespace: vigra
00250 
00251     These factories can be used to create argument objects when we
00252     are given instances or subclasses of \ref vigra::BasicImage (see
00253     \ref StandardImageTypes for instances defined per default).
00254     These factory functions access <TT>img.upperLeft()</TT>,
00255     <TT>img.lowerRight()</TT>, and <TT>img.accessor()</TT> to obtain the iterators
00256     and accessor for the given image (unless the accessor is
00257     given explicitly). The following factory functions are provided:
00258 
00259     <table>
00260     <tr><td>
00261         \htmlonly
00262         <th bgcolor="#f0e0c0" colspan=2 align=left>
00263         \endhtmlonly
00264         <TT>\ref vigra::BasicImage "vigra::BasicImage<SomeType>" img;</TT>
00265         \htmlonly
00266         </th>
00267         \endhtmlonly
00268     </td></tr>
00269     <tr><td>
00270 
00271     <TT>srcImageRange(img)</TT>
00272     </td><td>
00273         create argument object containing upper left, lower right, and
00274         default accessor of source image
00275 
00276     </td></tr>
00277     <tr><td>
00278 
00279     <TT>srcImageRange(img, SomeAccessor())</TT>
00280     </td><td>
00281         create argument object containing upper left, lower right
00282         of source image, and given accessor
00283 
00284     </td></tr>
00285     <tr><td>
00286 
00287     <TT>srcImage(img)</TT>
00288     </td><td>
00289         create argument object containing upper left, and
00290         default accessor of source image
00291 
00292     </td></tr>
00293     <tr><td>
00294 
00295     <TT>srcImage(img, SomeAccessor())</TT>
00296     </td><td>
00297         create argument object containing upper left
00298         of source image, and given accessor
00299 
00300     </td></tr>
00301     <tr><td>
00302 
00303     <TT>maskImage(img)</TT>
00304     </td><td>
00305         create argument object containing upper left, and
00306         default accessor of mask image
00307 
00308     </td></tr>
00309     <tr><td>
00310 
00311     <TT>maskImage(img, SomeAccessor())</TT>
00312     </td><td>
00313         create argument object containing upper left
00314         of mask image, and given accessor
00315 
00316     </td></tr>
00317     <tr><td>
00318 
00319     <TT>destImageRange(img)</TT>
00320     </td><td>
00321         create argument object containing upper left, lower right, and
00322         default accessor of destination image
00323 
00324     </td></tr>
00325     <tr><td>
00326 
00327     <TT>destImageRange(img, SomeAccessor())</TT>
00328     </td><td>
00329         create argument object containing upper left, lower right
00330         of destination image, and given accessor
00331 
00332     </td></tr>
00333     <tr><td>
00334 
00335     <TT>destImage(img)</TT>
00336     </td><td>
00337         create argument object containing upper left, and
00338         default accessor of destination image
00339 
00340     </td></tr>
00341     <tr><td>
00342 
00343     <TT>destImage(img, SomeAccessor())</TT>
00344     </td><td>
00345         create argument object containing upper left
00346         of destination image, and given accessor
00347 
00348     </td></tr>
00349     </table>
00350 
00351 
00352   \section MultiArrayBasedArgumentObjectFactories MultiArrayView Based Argument Object Factories
00353 
00354     <b>Include:</b> automatically included with 
00355        "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"<br>
00356     Namespace: vigra
00357 
00358     These factories can be used to create argument objects when we
00359     are given instances or subclasses of \ref vigra::MultiArrayView.
00360     These factory functions access <TT>array.traverser_begin()</TT>,
00361     <TT>array.traverser_end()</TT> to obtain the iterators. If no accessor is
00362     given, they use the <tt>AccessorTraits<T></tt> to determine the default 
00363     accessor associated with the array's value type <tt>T</tt>.
00364     The following factory functions are provided:
00365 
00366     <table>
00367     <tr><td>
00368         \htmlonly
00369         <th bgcolor="#f0e0c0" colspan=2 align=left>
00370         \endhtmlonly
00371         <TT>\ref vigra::MultiArrayView "vigra::MultiArrayView<N, SomeType>" array;</TT>
00372         \htmlonly
00373         </th>
00374         \endhtmlonly
00375     </td></tr>
00376     <tr><td>
00377 
00378     <TT>srcMultiArrayRange(img)</TT>
00379     </td><td>
00380         create argument object containing a \ref vigra::MultiIterator 
00381         marking the begin of the array, a shape object giving the desired
00382         shape of the array (possibly a subarray) and the default const accessor for
00383         <tt>SomeType</tt>
00384 
00385     </td></tr>
00386     <tr><td>
00387 
00388     <TT>srcMultiArrayRange(img, SomeAccessor())</TT>
00389     </td><td>
00390         create argument object containing a \ref vigra::MultiIterator 
00391         marking the begin of the array, a shape object giving the desired
00392         shape of the array (possibly a subarray) and the given accessor
00393 
00394     </td></tr>
00395     <tr><td>
00396 
00397     <TT>srcMultiArray(img)</TT>
00398     </td><td>
00399         create argument object containing a \ref vigra::MultiIterator
00400         marking the begin of the array, and the default const accessor for
00401         <tt>SomeType</tt>
00402 
00403     </td></tr>
00404     <tr><td>
00405 
00406     <TT>srcMultiArray(img, SomeAccessor())</TT>
00407     </td><td>
00408         create argument object containing a \ref vigra::MultiIterator 
00409         marking the begin of the array and the given accessor
00410 
00411     </td></tr>
00412     <tr><td>
00413 
00414     <TT>destMultiArrayRange(img)</TT>
00415     </td><td>
00416         create argument object containing a \ref vigra::MultiIterator 
00417         marking the begin of the array, a shape object giving the desired
00418         shape of the array (possibly a subarray) and the default accessor for
00419         <tt>SomeType</tt>
00420 
00421     </td></tr>
00422     <tr><td>
00423 
00424     <TT>destMultiArrayRange(img, SomeAccessor())</TT>
00425     </td><td>
00426         create argument object containing a \ref vigra::MultiIterator's 
00427         marking the begin of the array, a shape object giving the desired
00428         shape of the array (possibly a subarray) and the given accessor
00429 
00430     </td></tr>
00431     <tr><td>
00432 
00433     <TT>destMultiArray(img)</TT>
00434     </td><td>
00435         create argument object containing a \ref vigra::MultiIterator 
00436         marking the begin of the array and the default accessor for
00437         <tt>SomeType</tt>
00438 
00439     </td></tr>
00440     <tr><td>
00441 
00442     <TT>destMultiArray(img, SomeAccessor())</TT>
00443     </td><td>
00444         create argument object containing a \ref vigra::MultiIterator's 
00445         marking the begin of the array and the given accessor
00446 
00447     </td></tr>
00448     </table>
00449 
00450 
00451   \section IteratorBasedArgumentObjectFactories Iterator Based Argument Object Factories
00452 
00453     <b>\#include</b> "<a href="iteratortraits_8hxx-source.html">vigra/iteratortraits.hxx</a>"
00454     Namespace: vigra
00455 
00456     These factories can be used to create argument objects when we
00457     are given \ref ImageIterators.
00458     These factory functions use \ref vigra::IteratorTraits to
00459     get the default accessor for the given iterator unless the
00460     accessor is given explicitly. The following factory functions
00461     are provided:
00462 
00463     <table>
00464     <tr><td>
00465         \htmlonly
00466         <th bgcolor="#f0e0c0" colspan=2 align=left>
00467         \endhtmlonly
00468         <TT>\ref vigra::BasicImage::Iterator "vigra::BasicImage<SomeType>::Iterator" i1, i2;</TT>
00469         \htmlonly
00470         </th>
00471         \endhtmlonly
00472     </td></tr>
00473     <tr><td>
00474 
00475     <TT>srcIterRange(i1, i2)</TT>
00476     </td><td>
00477         create argument object containing the given iterators and
00478         corresponding default accessor (for source image)
00479 
00480     </td></tr>
00481     <tr><td>
00482 
00483     <TT>srcIterRange(i1, i2, SomeAccessor())</TT>
00484     </td><td>
00485         create argument object containing given iterators and
00486         accessor (for source image)
00487 
00488     </td></tr>
00489     <tr><td>
00490 
00491     <TT>srcIter(i1)</TT>
00492     </td><td>
00493         create argument object containing the given iterator and
00494         corresponding default accessor (for source image)
00495 
00496     </td></tr>
00497     <tr><td>
00498 
00499     <TT>srcIter(i1, SomeAccessor())</TT>
00500     </td><td>
00501         create argument object containing given iterator and
00502         accessor (for source image)
00503 
00504     </td></tr>
00505     <tr><td>
00506 
00507     <TT>maskIter(i1)</TT>
00508     </td><td>
00509         create argument object containing the given iterator and
00510         corresponding default accessor (for mask image)
00511 
00512     </td></tr>
00513     <tr><td>
00514 
00515     <TT>maskIter(i1, SomeAccessor())</TT>
00516     </td><td>
00517         create argument object containing given iterator and
00518         accessor (for mask image)
00519 
00520     </td></tr>
00521     <tr><td>
00522 
00523     <TT>destIterRange(i1, i2)</TT>
00524     </td><td>
00525         create argument object containing the given iterators and
00526         corresponding default accessor (for destination image)
00527 
00528     </td></tr>
00529     <tr><td>
00530 
00531     <TT>destIterRange(i1, i2, SomeAccessor())</TT>
00532     </td><td>
00533         create argument object containing given iterators and
00534         accessor (for destination image)
00535 
00536     </td></tr>
00537     <tr><td>
00538 
00539     <TT>destIter(i1)</TT>
00540     </td><td>
00541         create argument object containing the given iterator and
00542         corresponding default accessor (for destination image)
00543 
00544     </td></tr>
00545     <tr><td>
00546 
00547     <TT>destIter(i1, SomeAccessor())</TT>
00548     </td><td>
00549         create argument object containing given iterator and
00550         accessor (for destination image)
00551 
00552     </td></tr>
00553     </table>
00554 */
00555 
00556 template <class Iterator, class Accessor>
00557 inline triple<Iterator, Iterator, Accessor>
00558 srcIterRange(Iterator const & upperleft, Iterator const & lowerright, Accessor a)
00559 {
00560     return triple<Iterator, Iterator, Accessor>(upperleft, lowerright, a);
00561 }
00562 
00563 template <class Iterator, class Accessor>
00564 inline pair<Iterator, Accessor>
00565 srcIter(Iterator const & upperleft, Accessor a)
00566 {
00567     return pair<Iterator, Accessor>(upperleft, a);
00568 }
00569 
00570 template <class Iterator, class Accessor>
00571 inline pair<Iterator, Accessor>
00572 maskIter(Iterator const & upperleft, Accessor a)
00573 {
00574     return pair<Iterator, Accessor>(upperleft, a);
00575 }
00576 
00577 template <class Iterator, class Accessor>
00578 inline pair<Iterator, Accessor>
00579 destIter(Iterator const & upperleft, Accessor a)
00580 {
00581     return pair<Iterator, Accessor>(upperleft, a);
00582 }
00583 
00584 
00585 template <class Iterator, class Accessor>
00586 inline triple<Iterator, Iterator, Accessor>
00587 destIterRange(Iterator const & upperleft, Iterator const & lowerright, Accessor a)
00588 {
00589     return triple<Iterator, Iterator, Accessor>(upperleft, lowerright, a);
00590 }
00591 
00592 template <class Iterator>
00593 inline pair<Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>
00594 srcIter(Iterator const & upperleft)
00595 {
00596     return pair<Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>(
00597                   upperleft,
00598                   typename IteratorTraits<Iterator>::DefaultAccessor());
00599 }
00600 
00601 template <class Iterator>
00602 inline triple<Iterator, Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>
00603 srcIterRange(Iterator const & upperleft, Iterator const & lowerright)
00604 {
00605     return triple<Iterator, Iterator,
00606                   typename IteratorTraits<Iterator>::DefaultAccessor>(
00607                   upperleft, lowerright,
00608                   typename IteratorTraits<Iterator>::DefaultAccessor());
00609 }
00610 
00611 template <class Iterator>
00612 inline pair<Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>
00613 maskIter(Iterator const & upperleft)
00614 {
00615     return pair<Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>(
00616                   upperleft,
00617                   typename IteratorTraits<Iterator>::DefaultAccessor());
00618 }
00619 
00620 template <class Iterator>
00621 inline pair<Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>
00622 destIter(Iterator const & upperleft)
00623 {
00624     return pair<Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>(
00625                   upperleft,
00626                   typename IteratorTraits<Iterator>::DefaultAccessor());
00627 }
00628 
00629 template <class Iterator>
00630 inline triple<Iterator, Iterator, typename IteratorTraits<Iterator>::DefaultAccessor>
00631 destIterRange(Iterator const & upperleft, Iterator const & lowerright)
00632 {
00633     return triple<Iterator, Iterator,
00634                   typename IteratorTraits<Iterator>::DefaultAccessor>(
00635                   upperleft, lowerright,
00636                   typename IteratorTraits<Iterator>::DefaultAccessor());
00637 }
00638 
00639 //@}
00640 
00641 } // namespace vigra
00642 
00643 #endif // VIGRA_ITERATORTRAITS_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)