diff --git a/ChangeLog.md b/ChangeLog.md index 91fbf4630e..664979cf44 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -130,6 +130,8 @@ - *Kernel Package* - HyperRectDomain can now be empty (lowerBound == upperBound + diagonal(1)). Warning about the use of lexicographical order in comparison operators of PointVector. (Roland Denis, [#996](https://github.com/DGtal-team/DGtal/pull/996)) + - Adds generic linearization (point to index) and reverse process (index to point), specialized for HyperRectDomain. + (Roland Denis, [#1039](https://github.com/DGtal-team/DGtal/pull/1039)) - *Shapes Package* - Adds a vertex Iterator in the Mesh class in addition to the diff --git a/src/DGtal/images/ImageContainerBySTLVector.ih b/src/DGtal/images/ImageContainerBySTLVector.ih index c3f863b16c..e713b549d6 100644 --- a/src/DGtal/images/ImageContainerBySTLVector.ih +++ b/src/DGtal/images/ImageContainerBySTLVector.ih @@ -38,6 +38,7 @@ ////////////////////////////////////////////////////////////////////////////// #include +#include ////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------ @@ -179,112 +180,6 @@ DGtal::ImageContainerBySTLVector::className() const return "ImageContainerBySTLVector"; } -/////////////////////////////////////////////////////////////////////////////// -// Helper classes defined in the compilation unit (anonymous namespace) - -namespace -{ - - /** - * Class template for linearization of the coordinates of a Point. - * This class template is to be specialized for efficiency for dimensions 1, - * 2 and 3 to prevent the use of a loop in these cases. - * - * @tparam Domain an instance of HyperRectDomain - * @tparam dimension domain dimension - */ - template < typename Domain, int dimension> - struct linearizer - { - - typedef typename Domain::Point Point; - typedef typename Domain::Size Size; - - /** - * Compute the linearized offset of a point in a vector container. - * - * @param aPoint a point - * @param lowerBound lower bound of the image domain. - * @param extent extension of the image domain. - * - * @return the index - */ - static Size apply( const Point & aPoint, const Point & lowerBound, - const Point & extent ) - { - Size pos = aPoint[ 0 ] - lowerBound[ 0 ] ; - Size multiplier = 1; - for (typename Domain::Dimension k = 1 ; k < dimension ; ++k) - { - multiplier *= extent[ k-1 ]; - pos += multiplier * ( aPoint[ k ] - lowerBound[ k ] ); - } - return pos; - } - }; - - /** - * Specialization of the linearizer class for dimension 1. - * - */ - template < typename Domain > - struct linearizer< Domain, 1 > - { - typedef typename Domain::Point Point; - typedef typename Domain::Size Size; - - static Size apply( const Point & aPoint, - const Point & lowerBound, - const Point & /*extent*/ ) - { - return aPoint[ 0 ] - lowerBound[ 0 ]; - } - }; - - /** - * Specialization of the linearizer class for dimension 2. - * - */ - template < typename Domain > - struct linearizer< Domain, 2 > - { - typedef typename Domain::Point Point; - typedef typename Domain::Size Size; - - static Size apply( const Point & aPoint, - const Point & lowerBound, - const Point & extent ) - { - return ( aPoint[ 0 ] - lowerBound[ 0 ] ) + extent[ 0 ] * - (aPoint[ 1 ] - lowerBound[ 1 ] ); - } - }; - - /** - * Specialization of the linearizer class for dimension 3. - * - */ - template < typename Domain > - struct linearizer< Domain, 3 > - { - typedef typename Domain::Point Point; - typedef typename Domain::Size Size; - - static Size apply( const Point & aPoint, - const Point & lowerBound, - const Point & extent ) - { - Size res = aPoint[ 0 ] - lowerBound[ 0 ]; - Size multiplier = extent[ 0 ]; - res += multiplier * ( aPoint[ 1 ] - lowerBound[ 1 ] ); - multiplier *= extent[ 1 ]; - res += multiplier * ( aPoint[ 2 ] - lowerBound[ 2 ] ); - return res; - } - }; -} - - /////////////////////////////////////////////////////////////////////////////// // Internals - private : @@ -293,9 +188,7 @@ inline typename DGtal::ImageContainerBySTLVector::Size DGtal::ImageContainerBySTLVector::linearized(const Point &aPoint) const { - return linearizer::apply( aPoint, - myDomain.lowerBound(), - myExtent ); + return DGtal::Linearizer::getIndex( aPoint, myDomain.lowerBound(), myExtent ); } diff --git a/src/DGtal/kernel/domains/HyperRectDomain_Iterator.h b/src/DGtal/kernel/domains/HyperRectDomain_Iterator.h index c89adff2dc..9253471a1a 100644 --- a/src/DGtal/kernel/domains/HyperRectDomain_Iterator.h +++ b/src/DGtal/kernel/domains/HyperRectDomain_Iterator.h @@ -236,7 +236,7 @@ namespace DGtal if ( current_pos < TPoint::dimension ) ++myPoint[current_pos]; } - while (( current_pos < TPoint::dimension - 1 ) && + while (( current_pos + 1 < TPoint::dimension ) && ( myPoint[ current_pos ] > myupper[ current_pos ] ) ); } } @@ -279,7 +279,7 @@ namespace DGtal if ( current_pos < TPoint::dimension ) --myPoint[ current_pos ]; } - while (( current_pos < TPoint::dimension - 1 ) && + while (( current_pos + 1 < TPoint::dimension ) && ( myPoint[ current_pos ] < mylower[ current_pos ] ) ); } } @@ -464,7 +464,7 @@ namespace DGtal if ( current_pos < mySubDomain.size() ) ++myPoint[ mySubDomain[current_pos] ]; } - while (( current_pos < mySubDomain.size() - 1 ) && + while (( current_pos + 1 < mySubDomain.size() ) && ( myPoint[ mySubDomain[current_pos] ] > myupper[ mySubDomain[current_pos] ] ) ); } @@ -512,7 +512,7 @@ namespace DGtal if ( current_pos < mySubDomain.size() ) --myPoint[ mySubDomain[current_pos] ]; } - while (( current_pos < mySubDomain.size() - 1 ) && + while (( current_pos + 1 < mySubDomain.size() ) && ( myPoint[ mySubDomain[current_pos] ] < mylower[ mySubDomain[current_pos] ] ) ); } diff --git a/src/DGtal/kernel/domains/Linearizer.h b/src/DGtal/kernel/domains/Linearizer.h new file mode 100644 index 0000000000..7c7d35c15a --- /dev/null +++ b/src/DGtal/kernel/domains/Linearizer.h @@ -0,0 +1,191 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + **/ + +#pragma once + +/** + * @file Linearizer.h + * @author Roland Denis (\c roland.denis@univ-smb.fr ) + * LAboratory of MAthematics - LAMA (CNRS, UMR 5127), University of Savoie, France + * + * @date 2015/06/18 + * + * This file is part of the DGtal library. + */ + +#if defined(Linearizer_RECURSES) +#error Recursive header files inclusion detected in Linearizer.h +#else // defined(Linearizer_RECURSES) +/** Prevents recursive inclusion of headers. */ +#define Linearizer_RECURSES + +#if !defined Linearizer_h +/** Prevents repeated inclusion of headers. */ +#define Linearizer_h + +////////////////////////////////////////////////////////////////////////////// +// Inclusions +#include // Only for specialization purpose. +////////////////////////////////////////////////////////////////////////////// + +namespace DGtal +{ + + ///////////////////////////////////////////////////////////////////////////// + + /** + * @brief Tag (empty structure) specifying a row-major storage order. + * + * @see Linearizer + */ + struct RowMajorStorage {}; + + /** + * @brief Tag (empty structure) specifying a col-major storage order. + * + * @see Linearizer + */ + struct ColMajorStorage {}; + + ///////////////////////////////////////////////////////////////////////////// + /** + * @brief Aim: Linearization and de-linearization interface for domains. + * + * Description of class 'Linearizer'

+ * This class is empty but there is a specialization for HyperRectDomain. + * + * @tparam TDomain Type of the domain. + * @tparam TStorageOrder Storage Order (RowMajorStorage of ColMajorStorage). + * + */ + template < + typename TDomain, + typename TStorageOrder = ColMajorStorage + > + struct Linearizer; + + /** + * @brief Aim: Linearization and de-linearization interface for HyperRectDomain. + * + * This is a static class that provides point linearization (point to index) and de-linearization (index to point) for storages working on HyperRectDomain. + * + * The storage order can be specified by template (default is colum-major ordered). + * + * Example: + * @code + * typedef SpaceND<2> Space; + * tydedef HyperRectDomain Domain; + * typedef typename Space::Point Point; + * + * const Domain domain( Point(0, 1), Point(4, 3) ); + * + * typename Linearizer::Size id = Linearizer::getIndex( Point(2, 2), domain ); // returns 7. + * + * Point pt = Linearizer::getPoint( 7, domain); // returns Point(2,2). + * @endcode + * + * @tparam TSpace Type of the space of the HyperRectDomain (auto-deduced from TDomain template, see Linearizer). + * @tparam TStorageOrder Storage Order (RowMajorStorage of ColMajorStorage). + */ + template < + typename TSpace, + typename TStorageOrder + > + struct Linearizer< HyperRectDomain, TStorageOrder > + { + // Usefull typedefs + typedef HyperRectDomain Domain; ///< The domain type. + typedef typename TSpace::Point Point; ///< The point type. + typedef Point Extent; ///< The domain's extent type. + typedef typename TSpace::Size Size; ///< The space's size type. + + /** Linearized index of a point, given the domain lower-bound and extent. + * + * @param[in] aPoint The point to be linearized. + * @param[in] aLowerBound The lower-bound of the domain. + * @param[in] anExtent The extent of the domain. + * @return the linearized index of the point. + */ + static inline + Size getIndex( Point aPoint, Point const& aLowerBound, Extent const& anExtent ); + + /** Linearized index of a point, given the domain extent. + * + * The lower-bound of the domain is defined to the origin. + * + * @param[in] aPoint The Point to be linearized. + * @param[in] anExtent The extent of the domain. + * @return the linearized index of the point. + */ + static inline + Size getIndex( Point aPoint, Extent const& anExtent ); + + /** Linearized index of a point, given a domain. + * + * @param[in] aPoint The Point to be linearized. + * @param[in] aDomain The domain. + * @return the linearized index of the point. + */ + static inline + Size getIndex( Point aPoint, Domain const& aDomain ); + + /** De-linearization of an index, given the domain lower-bound and extent. + * + * @param[in] anIndex The linearized index. + * @param[in] aLowerBound The lower-bound of the domain. + * @param[in] anExtent The domain extent. + * @return the point whose linearized index is anIndex. + */ + static inline + Point getPoint( Size anIndex, Point const& aLowerBound, Extent const& anExtent ); + + /** De-linearization of an index, given the domain extent. + * + * The lower-bound of the domain is set to the origin. + * + * @param[in] anIndex The linearized index. + * @param[in] anExtent The domain extent. + * @return the point whose linearized index is anIndex. + */ + static inline + Point getPoint( Size anIndex, Extent const& anExtent ); + + /** De-linearization of an index, given a domain. + * + * @param[in] anIndex The linearized index. + * @param[in] aDomain The domain. + * @return the point whose linearized index is anIndex. + */ + static inline + Point getPoint( Size anIndex, Domain const& aDomain ); + + }; // end of class Linearizer + +} // namespace DGtal + + +/////////////////////////////////////////////////////////////////////////////// +// Includes inline functions. +#include "DGtal/kernel/domains/Linearizer.ih" + +// // +/////////////////////////////////////////////////////////////////////////////// + +#endif // !defined Linearizer_h + +#undef Linearizer_RECURSES +#endif // else defined(Linearizer_RECURSES) + diff --git a/src/DGtal/kernel/domains/Linearizer.ih b/src/DGtal/kernel/domains/Linearizer.ih new file mode 100644 index 0000000000..44be9dfd01 --- /dev/null +++ b/src/DGtal/kernel/domains/Linearizer.ih @@ -0,0 +1,222 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + **/ + +/** + * @file Linearizer.ih + * @author Roland Denis (\c roland.denis@univ-smb.fr ) + * LAboratory of MAthematics - LAMA (CNRS, UMR 5127), University of Savoie, France + * + * @date 2015/06/18 + * + * This file is part of the DGtal library. + */ + + +////////////////////////////////////////////////////////////////////////////// +#include +////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// IMPLEMENTATION of inline methods. +/////////////////////////////////////////////////////////////////////////////// + +namespace DGtal +{ + + /// Tools + namespace + { + + /** Helper that calculates the dimension index given the current linearization step. + * + * The step I is always decrementing from N-1 to 0. + * + * @tparam TStorageOrder Storage order (RowMajorStorage of ColMajorStorage). + * @tparam N Dimension of the space. + * @tparam I Current step. + */ + template < typename TStorageOrder, std::size_t N, std::size_t I > + struct linearizer_helper; + + template < std::size_t N, std::size_t I > + struct linearizer_helper< RowMajorStorage, N, I > + { + enum { dim = I }; ///< Dimension index related to the step I. + }; + + template < std::size_t N, std::size_t I > + struct linearizer_helper< ColMajorStorage, N, I > + { + enum { dim = N-1 - I }; ///< Dimension index related to the step I. + }; + + /** Templated static structure for linearization of the coordinates of a point. + * + * @tparam TSize Type of the linearizared index. + * @tparam TStorageOrder Storage order (RowMajorStorage of ColMajorStorage). + * @tparam N Dimension of the space. + * @tparam I Current step. + */ + template < typename TSize, typename TStorageOrder, std::size_t N, std::size_t I = N-1 > + struct linearizer_impl + { + + /** + * Return the linearized index from the coordinates of a point. + * + * @tparam TPoint Type of the point. + * @tparam TExtent Type of the domain's extent. + * @param[in] aPoint The point to linearize. + * @param[in] anExtent The extent of the domain. + * @return the linearized index of the point. + */ + template < typename TPoint, typename TExtent > + static inline + TSize apply( TPoint const& aPoint, TExtent const& anExtent ) + { + return + aPoint[ linearizer_helper::dim ] + + anExtent[ linearizer_helper::dim ] * linearizer_impl< TSize, TStorageOrder, N, I-1 >::apply( aPoint, anExtent ); + } + }; + + /** + * Specialization of the structure linearizer_impl for the last step. + * + * It is actually used as a terminate condition of the recursive process. + */ + template < typename TSize, typename TStorageOrder, std::size_t N > + struct linearizer_impl< TSize, TStorageOrder, N, 0 > + { + template < typename TPoint, typename TExtent > + static inline + TSize apply( TPoint const& aPoint, TExtent const& /* anExtent */ ) + { + return aPoint[ linearizer_helper::dim ]; + } + }; + + /** Templated static structure for de-linearization of a point index. + * + * @tparam TStorageOrder Storage order (RowMajorStorage of ColMajorStorage). + * @tparam N Dimension of the space. + * @tparam I Current step. + */ + template < typename TStorageOrder, std::size_t N, std::size_t I = N-1 > + struct delinearizer_impl + { + + /** + * Return the de-linearized point from the linearized index of the point. + * + * @tparam TPoint Type of the point. + * @tparam TExtent Type of the domain's extent. + * @tparam TSize Type of the linearized index. + * @param[out] aPoint The point after de-linearization. + * @param[in] anExtent The extent of the domain. + * @param[in] anIndex The linearized index of the point. + */ + template < typename TPoint, typename TExtent, typename TSize > + static inline + void apply( TPoint& aPoint, TExtent const& anExtent, TSize anIndex ) + { + typename TExtent::Scalar const dim_extent = anExtent[ linearizer_helper::dim ]; + aPoint[ linearizer_helper::dim ] = anIndex % dim_extent; + delinearizer_impl< TStorageOrder, N, I-1 >::apply( aPoint, anExtent, anIndex / dim_extent ); + } + }; + + /** + * Specialization of the structure delinearizer_impl for the last step. + * + * It is actually used as a terminate condition of the recursive process. + */ + template < typename TStorageOrder, std::size_t N > + struct delinearizer_impl< TStorageOrder, N, 0 > + { + template < typename TPoint, typename TExtent, typename TSize > + static inline + void apply( TPoint& aPoint, TExtent const& /* anExtent */, TSize anIndex ) + { + aPoint[ linearizer_helper::dim ] = anIndex; + } + }; + + } // anonymous namespace + + /// Linearized index of a point, given the domain lower-bound and extent. + template + typename Linearizer< HyperRectDomain, TStorageOrder >::Size + Linearizer< HyperRectDomain, TStorageOrder >:: + getIndex( Point aPoint, Point const& aLowerBound, Extent const& anExtent ) + { + aPoint -= aLowerBound; + return linearizer_impl::apply(aPoint, anExtent); + } + + /// Linearized index of a point, given the domain extent. + template + typename Linearizer< HyperRectDomain, TStorageOrder >::Size + Linearizer< HyperRectDomain, TStorageOrder >:: + getIndex( Point aPoint, Extent const& anExtent ) + { + return linearizer_impl::apply(aPoint, anExtent); + } + + /// Linearized index of a point, given a domain. + template + typename Linearizer< HyperRectDomain, TStorageOrder >::Size + Linearizer< HyperRectDomain, TStorageOrder >:: + getIndex( Point aPoint, Domain const& aDomain ) + { + return linearizer_impl::apply(aPoint - aDomain.lowerBound(), aDomain.upperBound()-aDomain.lowerBound()+Point::diagonal(1)); + } + + /// De-linearization of an index, given the domain lower-bound and extent. + template + typename Linearizer< HyperRectDomain, TStorageOrder >::Point + Linearizer< HyperRectDomain, TStorageOrder >:: + getPoint( Size anIndex, Point const& aLowerBound, Extent const& anExtent ) + { + Point point; + delinearizer_impl::apply(point, anExtent, anIndex); + return point + aLowerBound; + } + + /// De-linearization of an index, given the domain extent. + template + typename Linearizer< HyperRectDomain, TStorageOrder >::Point + Linearizer< HyperRectDomain, TStorageOrder >:: + getPoint( Size anIndex, Extent const& anExtent ) + { + Point point; + delinearizer_impl::apply(point, anExtent, anIndex); + return point; + } + + /// De-linearization of an index, given a domain. + template + typename Linearizer< HyperRectDomain, TStorageOrder >::Point + Linearizer< HyperRectDomain, TStorageOrder >:: + getPoint( Size anIndex, Domain const& aDomain ) + { + Point point; + delinearizer_impl::apply(point, aDomain.upperBound()-aDomain.lowerBound()+Point::diagonal(1), anIndex); + return point + aDomain.lowerBound(); + } + +} // namespace DGtal + diff --git a/tests/kernel/CMakeLists.txt b/tests/kernel/CMakeLists.txt index 31343f2468..5c8cc403dd 100644 --- a/tests/kernel/CMakeLists.txt +++ b/tests/kernel/CMakeLists.txt @@ -12,6 +12,7 @@ SET(DGTAL_TESTS_SRC_KERNEL testBasicPointFunctors testEmbedder testPointPredicateConcepts + testLinearizer ) diff --git a/tests/kernel/testLinearizer.cpp b/tests/kernel/testLinearizer.cpp new file mode 100644 index 0000000000..26f9a8fbed --- /dev/null +++ b/tests/kernel/testLinearizer.cpp @@ -0,0 +1,349 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + **/ + +/** + * @file testLinearizer.cpp + * @ingroup Tests + * @author Roland Denis (\c roland.denis@univ-smb.fr ) + * + * + * @date 2015/09/10 + * + * This file is part of the DGtal library + */ + +/** + * Description of testLinearizer.cpp

+ * Aim: Tests of linearization (point to index) et reverse process (index to point) for HyperRectDomain. + */ + +#include +#include + +#include "DGtalCatch.h" + +#include +#include +#include + +using namespace DGtal; + +// Previous version of the linearizer, used here for reference results. +namespace +{ + + /** + * Class template for linearization of the coordinates of a Point. + * This class template is to be specialized for efficiency for dimensions 1, + * 2 and 3 to prevent the use of a loop in these cases. + * + * @tparam Domain an instance of HyperRectDomain + * @tparam dimension domain dimension + */ + template < typename Domain, int dimension> + struct linearizer + { + + typedef typename Domain::Point Point; + typedef typename Domain::Size Size; + + /** + * Compute the linearized offset of a point in a vector container. + * + * @param aPoint a point + * @param lowerBound lower bound of the image domain. + * @param extent extension of the image domain. + * + * @return the index + */ + static Size apply( const Point & aPoint, const Point & lowerBound, + const Point & extent ) + { + Size pos = aPoint[ 0 ] - lowerBound[ 0 ] ; + Size multiplier = 1; + for (typename Domain::Dimension k = 1 ; k < dimension ; ++k) + { + multiplier *= extent[ k-1 ]; + pos += multiplier * ( aPoint[ k ] - lowerBound[ k ] ); + } + return pos; + } + }; + + /** + * Specialization of the linearizer class for dimension 1. + * + */ + template < typename Domain > + struct linearizer< Domain, 1 > + { + typedef typename Domain::Point Point; + typedef typename Domain::Size Size; + + static Size apply( const Point & aPoint, + const Point & lowerBound, + const Point & /*extent*/ ) + { + return aPoint[ 0 ] - lowerBound[ 0 ]; + } + }; + + /** + * Specialization of the linearizer class for dimension 2. + * + */ + template < typename Domain > + struct linearizer< Domain, 2 > + { + typedef typename Domain::Point Point; + typedef typename Domain::Size Size; + + static Size apply( const Point & aPoint, + const Point & lowerBound, + const Point & extent ) + { + return ( aPoint[ 0 ] - lowerBound[ 0 ] ) + extent[ 0 ] * + (aPoint[ 1 ] - lowerBound[ 1 ] ); + } + }; + + /** + * Specialization of the linearizer class for dimension 3. + * + */ + template < typename Domain > + struct linearizer< Domain, 3 > + { + typedef typename Domain::Point Point; + typedef typename Domain::Size Size; + + static Size apply( const Point & aPoint, + const Point & lowerBound, + const Point & extent ) + { + Size res = aPoint[ 0 ] - lowerBound[ 0 ]; + Size multiplier = extent[ 0 ]; + res += multiplier * ( aPoint[ 1 ] - lowerBound[ 1 ] ); + multiplier *= extent[ 1 ]; + res += multiplier * ( aPoint[ 2 ] - lowerBound[ 2 ] ); + return res; + } + }; +} + + +/// Converter between col-major and row-major storage order. +template < typename StorageOrder > +struct PointConverter; + +template <> +struct PointConverter +{ + template < typename TPoint > + static inline + TPoint apply( TPoint const& aPoint ) + { + return aPoint; + } +}; + +template <> +struct PointConverter +{ + template < typename TPoint > + static inline + TPoint apply( TPoint const& aPoint ) + { + TPoint result; + for ( std::size_t i = 0 ; i < TPoint::dimension ; ++i ) + result[i] = aPoint[ TPoint::dimension - i - 1 ]; + + return result; + } +}; + +#define TEST_LINEARIZER( N , ORDER ) \ +TEST_CASE( "Testing Linearizer in dimension " #N " with " #ORDER, "[test][dim" #N "][" #ORDER "]" )\ +{\ +\ + typedef SpaceND Space;\ + typedef HyperRectDomain Domain;\ + typedef Space::Point Point;\ +\ + typedef linearizer RefLinearizer;\ + typedef Linearizer NewLinearizer;\ +\ + typedef PointConverter RefConverter;\ +\ + std::size_t size = 1e3;\ +\ + Point lowerBound;\ + for ( std::size_t i = 0 ; i < N ; ++i )\ + lowerBound[i] = 1 + 7*i;\ +\ + std::size_t dim_size = std::size_t( std::pow( double(size), 1./N ) + 0.5 );\ + Point upperBound;\ + for ( std::size_t i = 0; i < N ; ++i )\ + upperBound[i] = lowerBound[i] + dim_size + i;\ +\ + Domain domain( lowerBound, upperBound );\ + Point extent = upperBound - lowerBound + Point::diagonal(1);\ +\ + Point refLowerBound = RefConverter::apply(lowerBound);\ + Point refExtent = RefConverter::apply(extent);\ +\ + SECTION( "Testing getIndex(Point, Point, Extent) syntax" )\ + {\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + REQUIRE(( RefLinearizer::apply( RefConverter::apply(*it), refLowerBound, refExtent ) == NewLinearizer::getIndex( *it, lowerBound, extent ) ));\ + }\ +\ + SECTION( "Testing getIndex(Point, Extent) syntax" )\ + {\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + REQUIRE(( RefLinearizer::apply( RefConverter::apply(*it), refLowerBound, refExtent ) == NewLinearizer::getIndex( *it - lowerBound, extent ) ));\ + }\ +\ + SECTION( "Testing getIndex(Point, Domain) syntax" )\ + {\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + REQUIRE(( RefLinearizer::apply( RefConverter::apply(*it), refLowerBound, refExtent ) == NewLinearizer::getIndex( *it, domain ) ));\ + }\ +\ + SECTION( "Testing getPoint(Index, Point, Extent) syntax" )\ + {\ + for ( std::size_t i = 0; i < domain.size(); ++i )\ + REQUIRE(( RefLinearizer::apply( RefConverter::apply( NewLinearizer::getPoint( i, lowerBound, extent ) ), refLowerBound, refExtent ) == i ));\ + }\ +\ + SECTION( "Testing getPoint(Index, Extent) syntax" )\ + {\ + for ( std::size_t i = 0; i < domain.size(); ++i )\ + REQUIRE(( RefLinearizer::apply( RefConverter::apply( NewLinearizer::getPoint( i, extent ) + lowerBound ), refLowerBound, refExtent ) == i ));\ + }\ +\ + SECTION( "Testing getPoint(Index, Domain) syntax" )\ + {\ + for ( std::size_t i = 0; i < domain.size(); ++i )\ + REQUIRE(( RefLinearizer::apply( RefConverter::apply( NewLinearizer::getPoint( i, domain ) ), refLowerBound, refExtent ) == i ));\ + }\ +} + +#define BENCH_LINEARIZER( N , ORDER ) \ +TEST_CASE( "Benchmarking Linearizer in dimension " #N " with " #ORDER, "[.bench][dim" #N "][" #ORDER "]" )\ +{\ +\ + typedef SpaceND Space;\ + typedef HyperRectDomain Domain;\ + typedef Space::Point Point;\ +\ + typedef linearizer RefLinearizer;\ + typedef Linearizer NewLinearizer;\ +\ + typedef PointConverter RefConverter;\ +\ + std::size_t size = 1e8;\ +\ + Point lowerBound;\ + for ( std::size_t i = 0 ; i < N ; ++i )\ + lowerBound[i] = 1 + 7*i;\ +\ + std::size_t dim_size = std::size_t( std::pow( double(size), 1./N ) + 0.5 );\ + Point upperBound;\ + for ( std::size_t i = 0; i < N ; ++i )\ + upperBound[i] = lowerBound[i] + dim_size + i;\ +\ + Domain domain( lowerBound, upperBound );\ + Point extent = upperBound - lowerBound + Point::diagonal(1);\ +\ + Point refLowerBound = RefConverter::apply(lowerBound);\ + Point refExtent = RefConverter::apply(extent);\ +\ + std::size_t sum = 0;\ +\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + sum += RefLinearizer::apply( RefConverter::apply(*it), refLowerBound, refExtent );\ + REQUIRE( sum > 0 );\ + sum = 0;\ +\ + SECTION( "Benchmarking reference linearizer" )\ + {\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + sum += RefLinearizer::apply( RefConverter::apply(*it), refLowerBound, refExtent );\ + }\ +\ + SECTION( "Benchmarking getIndex(Point, Point, Extent) syntax" )\ + {\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + sum += NewLinearizer::getIndex( *it, lowerBound, extent );\ + }\ +\ + SECTION( "Benchmarking getIndex(Point, Extent) syntax" )\ + {\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + sum += NewLinearizer::getIndex( *it, extent );\ + }\ +\ + SECTION( "Benchmarking getIndex(Point, Domain) syntax" )\ + {\ + for ( Domain::ConstIterator it = domain.begin(), it_end = domain.end(); it != it_end ; ++it )\ + sum += NewLinearizer::getIndex( *it, domain );\ + }\ +\ + SECTION( "Benchmarking getPoint(Index, Point, Extent) syntax" )\ + {\ + for ( std::size_t i = 0; i < domain.size(); ++i )\ + sum += NewLinearizer::getPoint( i, lowerBound, extent )[N-1];\ + }\ +\ + SECTION( "Benchmarking getPoint(Index, Extent) syntax" )\ + {\ + for ( std::size_t i = 0; i < domain.size(); ++i )\ + sum += NewLinearizer::getPoint( i, extent )[N-1];\ + }\ +\ + SECTION( "Benchmarking getPoint(Index, Domain) syntax" )\ + {\ + for ( std::size_t i = 0; i < domain.size(); ++i )\ + sum += NewLinearizer::getPoint( i, domain )[N-1];\ + }\ +\ + REQUIRE( sum > 0 );\ +} + +TEST_LINEARIZER( 1, ColMajorStorage ) +TEST_LINEARIZER( 2, ColMajorStorage ) +TEST_LINEARIZER( 3, ColMajorStorage ) +TEST_LINEARIZER( 4, ColMajorStorage ) +TEST_LINEARIZER( 5, ColMajorStorage ) + +TEST_LINEARIZER( 1, RowMajorStorage ) +TEST_LINEARIZER( 2, RowMajorStorage ) +TEST_LINEARIZER( 3, RowMajorStorage ) +TEST_LINEARIZER( 4, RowMajorStorage ) +TEST_LINEARIZER( 5, RowMajorStorage ) + +BENCH_LINEARIZER( 1, ColMajorStorage ) +BENCH_LINEARIZER( 2, ColMajorStorage ) +BENCH_LINEARIZER( 3, ColMajorStorage ) +BENCH_LINEARIZER( 4, ColMajorStorage ) +BENCH_LINEARIZER( 5, ColMajorStorage ) + +BENCH_LINEARIZER( 1, RowMajorStorage ) +BENCH_LINEARIZER( 2, RowMajorStorage ) +BENCH_LINEARIZER( 3, RowMajorStorage ) +BENCH_LINEARIZER( 4, RowMajorStorage ) +BENCH_LINEARIZER( 5, RowMajorStorage )