#ifndef __JGRIDBOUNDS__ #define __JGRIDBOUNDS__ #include "JLang/JException.hh" #include "JTools/JMultiKey.hh" namespace JTOOLS { namespace { using JLANG::JValueOutOfRange; } /** * Abstract interface to specify boundary conditions of an equidistant collection of elements. * This abstract class provides for the methods getPosition() and getKey(). * Note that the method getKey() returns the lower (upper) limit for argument values * (0) and (number of keys - 1), respectively. */ template class JAbstractGridBounds { public: /** * Virtual destructor. */ virtual ~JAbstractGridBounds() {} /** * Get number of keys. * * \return number of keys */ virtual unsigned int getNumberOfKeys() const = 0; /** * Get lower limit. * * \return lower key */ virtual JKey_t getLowerKey() const = 0; /** * Get upper limit. * * \return upper key */ virtual JKey_t getUpperKey() const = 0; /** * Get bin position (starting at 0). * The bin position could be less than zero or larger than the number of keys. * * \param x key * \return index */ virtual int getPosition(const JKey_t x) const { return (int) ((getNumberOfKeys() - 1) * (x - getLowerKey()) / (getUpperKey() - getLowerKey())); } /** * Get index of bin (starting at 0). * The index is larger or equal zero and less than the number of keys. * * \param x key * \return index */ virtual int getIndex(const JKey_t x) const { const int min = 0; const int max = getNumberOfKeys() - 1; const int pos = getPosition(x); if (pos < min) return min; if (pos > max) return max; return pos; } /** * Get lower edge of bin. * * \param index index of bin * \return key */ virtual JKey_t getKey(const int index) const { return getLowerKey() + index * ((getUpperKey() - getLowerKey()) / (getNumberOfKeys() - 1)); } /** * Get bin width. * * \return bin width */ virtual JKey_t getBinWidth() const { return (getUpperKey() - getLowerKey()) / (getNumberOfKeys() - 1); } }; /** * Data structure that implements the JAbstractGridBounds<> interface. */ template class JGridBounds : public JAbstractGridBounds { public: /** * Default constructor. */ JGridBounds() : JAbstractGridBounds(), number_of_keys(0), lower_key(), upper_key() {} /** * Constructor. * * \param bounds (abstract) grid bounds */ JGridBounds(const JAbstractGridBounds& bounds) : JAbstractGridBounds(), number_of_keys(bounds.getNumberOfKeys()), lower_key (bounds.getLowerKey()), upper_key (bounds.getUpperKey()) {} /** * Constructor. * * \param numberOfKeys number of keys * \param lowerKey lower key * \param upperKey upper key */ JGridBounds(const unsigned int numberOfKeys, const JKey_t lowerKey, const JKey_t upperKey) : JAbstractGridBounds(), number_of_keys(numberOfKeys), lower_key(lowerKey), upper_key(upperKey) { if (number_of_keys == 1) throw JValueOutOfRange("JGridBounds()"); if (lower_key == upper_key) throw JValueOutOfRange("JGridBounds()"); } virtual unsigned int getNumberOfKeys() const { return number_of_keys; } virtual JKey_t getLowerKey() const { return lower_key; } virtual JKey_t getUpperKey() const { return upper_key; } protected: unsigned int number_of_keys; JKey_t lower_key; JKey_t upper_key; }; /** * Abstract interface for configuring of multi-dimensional grid. */ template class JAbstractMultiGridBounds { public: /** * Virtual destructor. */ virtual ~JAbstractMultiGridBounds() {} /** * Evaluate grid bounds as a function of composite key. * * \param key composite key * \return grid bounds */ virtual JGridBounds operator()(const JMultiKey& key) const = 0; }; /** * Template specialisation of abstract interface for configuring of upper- of multi-dimensional grid. */ template class JAbstractMultiGridBounds<0, JKey_t> { public: /** * Virtual destructor. */ virtual ~JAbstractMultiGridBounds() {} /** * Evaluate grid bounds. * * \return grid bounds */ virtual JGridBounds operator()() const = 0; }; /** * Data structure that implements the JAbstractMultiGridBounds<> interface. */ template class JMultiGridBounds : public JAbstractMultiGridBounds { public: /** * Constructor. * * \param numberOfKeys number of keys * \param lowerKey lower key * \param upperKey upper key */ JMultiGridBounds(const unsigned int& numberOfKeys, const JKey_t& lowerKey, const JKey_t& upperKey) : bounds(numberOfKeys, lowerKey, upperKey) {} /** * Evaluate grid bounds as a function of composite key. * * \param key composite key * \return grid bounds */ JGridBounds operator()(const JMultiKey& key) const { return bounds; } protected: JGridBounds bounds; }; /** * Data structure that implements the JAbstractMultiGridBounds<> interface. */ template class JMultiGridBounds<0, JKey_t> : public JAbstractMultiGridBounds<0, JKey_t> { public: /** * Constructor. * * \param numberOfKeys number of keys * \param lowerKey lower key * \param upperKey upper key */ JMultiGridBounds(const unsigned int& numberOfKeys, const JKey_t& lowerKey, const JKey_t& upperKey) : bounds(numberOfKeys, lowerKey, upperKey) {} /** * Evaluate grid bounds. * * \return grid bounds */ JGridBounds operator()() const { return bounds; } protected: JGridBounds bounds; }; /** * Helper method for JGridBounds. * * \param number_of_keys number of keys * \param lower_key lower key * \param upper_key upper key * \return JGridBounds<> */ template inline JGridBounds make_grid_bounds(const unsigned int& number_of_keys, const JKey_t& lower_key, const JKey_t& upper_key) { return JGridBounds(number_of_keys, lower_key, upper_key); } /** * Helper method for JMultiGridBounds. * * \param number_of_keys number of keys * \param lower_key lower key * \param upper_key upper key * \return JMultiGridBounds<> */ template inline JMultiGridBounds make_multigrid_bounds(const unsigned int& number_of_keys, const JKey_t& lower_key, const JKey_t& upper_key) { return JMultiGridBounds(number_of_keys, lower_key, upper_key); } } #endif