#ifndef __JTOOLS__JMULTIMAP__ #define __JTOOLS__JMULTIMAP__ #include "JLang/JEquals.hh" #include "JLang/JForwardIterator.hh" #include "JMath/JMath.hh" #include "JTools/JDistance.hh" #include "JTools/JPair.hh" #include "JTools/JMultiPair.hh" #include "JTools/JMapList.hh" #include "JTools/JAbstractMultiMap.hh" #include "JTools/JMultiKey.hh" /** * \file * * General purpose multidimensional map based on a type list of maps. * \author mdejong */ namespace JTOOLS {} namespace JPP { using namespace JTOOLS; } namespace JTOOLS { using JMATH::JMath; using JLANG::JEquals; using JLANG::JForwardIterator; /** * Multidimensional map. * * The first template parameter refers to the data type of the (multidimensional) key; * the second to the data type of the overall mapped value; * the third to the list of maps used; and * the fourth to the distance operator. * * In addition to the standard STL iterators, * there are super iteretors for linear access to the multidimensional map.\n * The access from a super iterator to the actual elements in the multidimensional map * is handled via the usual dereference and pointer operators.\n * The multidimensional key (see JTOOLS::JMultiKey) and value can directly be obtained * via member methods %getKey() and %getValue(), respectively. */ template > class JMultiMap; /** * Template specialisation of JMultiMap for map list with at least one map. */ template class JHead_t, class JTail_t, class JDistance_t> class JMultiMap, JDistance_t> : public JHead_t, JDistance_t>, public JMath< JMultiMap, JDistance_t> > { public: enum { NUMBER_OF_DIMENSIONS = JMapLength< JMapList >::value }; typedef JHead_t, JDistance_t> map_type; typedef JAbscissa_t abscissa_type; typedef JOrdinate_t ordinate_type; typedef typename map_type::key_type key_type; typedef typename map_type::mapped_type mapped_type; typedef typename map_type::value_type value_type; typedef typename map_type::const_iterator const_iterator; typedef typename map_type::const_reverse_iterator const_reverse_iterator; typedef typename map_type::iterator iterator; typedef typename map_type::reverse_iterator reverse_iterator; using map_type::insert; using map_type::configure; using map_type::get; /** * Default constructor. */ JMultiMap() {} /** * Add map. * * \param map multimap * \return this multimap */ JMultiMap& add(const JMultiMap& map) { static_cast(*this).add(static_cast(map)); return *this; } /** * Subtract map. * * \param map multimap * \return this multimap */ JMultiMap& sub(const JMultiMap& map) { static_cast(*this).sub(static_cast(map)); return *this; } /** * Scale contents. * * \param value multiplication factor * \return this multimap */ JMultiMap& mul(const double value) { static_cast(*this).mul(value); return *this; } /** * Scale contents. * * \param value division factor * \return this multimap */ JMultiMap& div(const double value) { static_cast(*this).div(value); return *this; } /** * Function application to each element of this multimap. * * \param function function */ template void for_each(const JFunction_t& function) { function(*this); for (iterator i = this->begin(); i != this->end(); ++i) { i->getY().for_each(function); } } /** * Configure multidimensional map. * * \param bounds multidimensional bounds */ void configure(const JAbstractMultiMap& bounds) { this->configure(JMultiKey<0, abscissa_type>(), bounds); } /** * Configure multidimensional map. * * \param key multidimensional key * \param bounds multidimensional bounds */ template void configure(const JMultiKey& key, const JAbstractMultiMap& bounds) { this->configure(bounds(key)); for (iterator i = this->begin(); i != this->end(); ++i) { i->getY().configure(JMultiKey(key,i->getX()), bounds); } } private: /** * Base class for multidimensional iterator. */ template struct iterator_base : public JEquals< iterator_base > { typedef std::pair range_type; typedef typename second_iterator::value_type value_type; typedef JMultiKey multikey_type; typedef JMultiPair multipair_type; /** * Auxiliary class for smart pointer. */ struct pointer_type : private JPair { /** * Constructor. * * \param key key * \param value value */ pointer_type(const key_type key, second_iterator& value) : JPair(key, value) {} /** * Smart pointer operator. * * \return pointer to object */ const JPair* operator->() const { return this; } }; /** * Smart pointer operator. * * \return pointer to pair of iterators */ pointer_type operator->() { return pointer_type(i->getX(), second); } /** * Dereference operator. * * \return multidimensional pair */ multipair_type operator*() { return multipair_type(i->getX(), *second); } /** * Equality of super iterator. * * \param cursor super iterator * \return true if equal; else false */ bool equals(const iterator_base& cursor) const { return i == cursor.i && (i == range.second || second.equals(cursor.second)); } /** * Get multidimensional key. * * \return key */ multikey_type getKey() const { return multikey_type(i->getX(), second.getKey()); } /** * Get value. * * \return value */ value_type& getValue() { return this->second.getValue(); } protected: range_type range; first_iterator i; second_iterator second; }; /** * Helper class for multidimensional iterator. */ template struct iterator_helper : public iterator_base, public JForwardIterator< iterator_helper > { /** * Default constructor. */ iterator_helper() {} /** * Constructor. * * \param __begin begin of data * \param __end end of data */ iterator_helper(first_iterator __begin, first_iterator __end) { this->range = std::make_pair(__begin, __end); for (this->i = this->range.first; this->i != this->range.second; ++(this->i)) { this->second = this->i->getY().super_begin(); if (this->second != this->i->getY().super_end()) { break; } } } /** * Increment super iterator. * * \return true if valid; else false */ virtual bool increment() override { if (!this->second.increment()) { while (++(this->i) != this->range.second) { this->second = this->i->getY().super_begin(); if (this->second != this->i->getY().super_end()) { break; } } } return this->i != this->range.second; } }; /** * Helper class for multidimensional reverse iterator. */ template struct reverse_iterator_helper : public iterator_base, public JForwardIterator< reverse_iterator_helper > { /** * Default constructor. */ reverse_iterator_helper() {} /** * Constructor. * * \param __begin begin of data * \param __end end of data */ reverse_iterator_helper(first_iterator __begin, first_iterator __end) { this->range = std::make_pair(__begin, __end); for (this->i = this->range.first; this->i != this->range.second; ++(this->i)) { this->second = this->i->getY().super_rbegin(); if (this->second != this->i->getY().super_rend()) { break; } } } /** * Increment super iterator. * * \return true if valid; else false */ virtual bool increment() override { if (!this->second.increment()) { while (++(this->i) != this->range.second) { this->second = this->i->getY().super_rbegin(); if (this->second != this->i->getY().super_rend()) { break; } } } return this->i != this->range.second; } }; public: class super_const_iterator; // forward declaration /** * Multidimensional iterator. */ class super_iterator : public iterator_helper { public: friend class JMultiMap; friend class super_const_iterator; /** * Default constructor. */ super_iterator() {} private: /** * Constructor. * * \param __begin begin of data * \param __end end of data */ super_iterator(iterator __begin, iterator __end) : iterator_helper(__begin, __end) {} }; /** * Multidimensional const_iterator. */ class super_const_iterator : public iterator_helper, public JEquals { public: friend class JMultiMap; /** * Default constructor. */ super_const_iterator() {} /** * Copy constructor. * * \param cursor super iterator */ super_const_iterator(const super_iterator& cursor) { this->range = cursor.range; this->i = cursor.i; this->second = cursor.second; } /** * Equality of super iterator. * * \param cursor super iterator * \return true if equal; else false */ bool equals(const super_const_iterator& cursor) const { return static_cast&>(*this).equals(cursor); } /** * Equality of super iterator. * * \param cursor super iterator * \return true if equal; else false */ bool equals(const super_iterator& cursor) const { return equals(super_const_iterator(cursor)); } private: /** * Constructor. * * \param __begin begin of data * \param __end end of data */ super_const_iterator(const_iterator __begin, const_iterator __end) : iterator_helper(__begin, __end) {} }; class super_const_reverse_iterator; // forward declaration /** * Multidimensional reverse iterator. */ class super_reverse_iterator : public reverse_iterator_helper { public: friend class JMultiMap; friend class super_const_reverse_iterator; /** * Default constructor. */ super_reverse_iterator() {} private: /** * Constructor. * * \param __begin reverse begin of data * \param __end reverse end of data */ super_reverse_iterator(reverse_iterator __begin, reverse_iterator __end) : reverse_iterator_helper(__begin, __end) {} }; /** * Multidimensional const reverse iterator. */ class super_const_reverse_iterator : public reverse_iterator_helper, public JEquals { public: friend class JMultiMap; /** * Default constructor. */ super_const_reverse_iterator() {} /** * Copy constructor. * * \param cursor super reverse iterator */ super_const_reverse_iterator(super_reverse_iterator cursor) { this->range = cursor.range; this->i = cursor.i; this->second = cursor.second; } /** * Equality of super reverse iterator. * * \param cursor super reverse iterator * \return true if equal; else false */ bool equals(const super_const_reverse_iterator& cursor) const { return static_cast&>(*this).equals(cursor); } /** * Equality of super reverse iterator. * * \param cursor super reverse iterator * \return true if equal; else false */ bool equals(const super_reverse_iterator& cursor) const { return equals(super_const_reverse_iterator(cursor)); } private: /** * Constructor. * * \param __begin begin of data * \param __end end of data */ super_const_reverse_iterator(const_reverse_iterator __begin, const_reverse_iterator __end) : reverse_iterator_helper(__begin, __end) {} }; /** * Get super iterator to begin of data. * * \return super iterator */ super_const_iterator super_begin() const { return super_const_iterator(this->begin(), this->end()); } /** * Get super iterator to reverse begin of data * * \return super reverse iterator */ super_const_reverse_iterator super_rbegin() const { return super_const_reverse_iterator(this->rbegin(), this->rend()); } /** * Get super iterator to end of data. * * \return super iterator */ super_const_iterator super_end() const { return super_const_iterator(this->end(), this->end()); } /** * Get super iterator to reverse end of data. * * \return super reverse iterator */ super_const_reverse_iterator super_rend() const { return super_const_reverse_iterator(this->rend(), this->rend()); } /** * Get super iterator to begin of data. * * \return super iterator */ super_iterator super_begin() { return super_iterator(this->begin(), this->end()); } /** * Get super iterator to reverse begin of data. * * \return super iterator */ super_reverse_iterator super_rbegin() { return super_reverse_iterator(this->rbegin(), this->rend()); } /** * Get super iterator to end of data. * * \return super iterator */ super_iterator super_end() { return super_iterator(this->end(), this->end()); } /** * Get super iterator to reverse end of data. * * \return super iterator */ super_reverse_iterator super_rend() { return super_reverse_iterator(this->rend(), this->rend()); } /** * Get value. * * \param key multidimensional key * \return value */ ordinate_type& get(const JMultiKey& key) { return this->get(key.first).get(key.second); } /** * Insert element. * * \param key multidimensional key * \param value value */ void insert(const JMultiKey& key, const ordinate_type& value) { (*this)[key.first].insert(key.second, value); } /** * Insert element. * * \param value multidimensional pair */ void insert(const JMultiPair& value) { (*this)[value.first].insert(value.second); } /** * Insert element. * * \param value multidimensional pair */ void insert(const JMultiPair& value) { (*this)[value.first].insert(value.second); } }; /** * Terminator class of recursive JMultiMap class. */ template class JHead_t, class JDistance_t> class JMultiMap, JDistance_t> : public JHead_t, public JMath< JMultiMap, JDistance_t> > { public: enum { NUMBER_OF_DIMENSIONS = 1 }; typedef JHead_t map_type; typedef JAbscissa_t abscissa_type; typedef JOrdinate_t ordinate_type; typedef typename map_type::key_type key_type; typedef typename map_type::mapped_type mapped_type; typedef typename map_type::value_type value_type; typedef typename map_type::const_iterator const_iterator; typedef typename map_type::const_reverse_iterator const_reverse_iterator; typedef typename map_type::iterator iterator; typedef typename map_type::reverse_iterator reverse_iterator; using map_type::insert; using map_type::configure; using map_type::get; /** * Default constructor. */ JMultiMap() {} /** * Add map. * * \param map multimap * \return this multimap */ JMultiMap& add(const JMultiMap& map) { static_cast(*this).add(static_cast(map)); return *this; } /** * Subtract map. * * \param map multimap * \return this multimap */ JMultiMap& sub(const JMultiMap& map) { static_cast(*this).sub(static_cast(map)); return *this; } /** * Scale contents. * * \param value multiplication factor * \return this multimap */ JMultiMap& mul(const double value) { static_cast(*this).mul(value); return *this; } /** * Scale contents. * * \param value division factor * \return this multimap */ JMultiMap& div(const double value) { static_cast(*this).div(value); return *this; } /** * Termination of function application. * * \param function function */ template void for_each(const JFunction_t& function) { function(*this); } /** * Configure multidimensional map. * * \param bounds multidimensional bounds */ void configure(const JAbstractMultiMap& bounds) { this->configure(JMultiKey<0, abscissa_type>(), bounds); } /** * Configure multidimensional map. * * \param key multidimensional key * \param bounds multidimensional bounds */ template void configure(const JMultiKey& key, const JAbstractMultiMap& bounds) { this->configure(bounds(key)); } private: /** * Helper class for multidimensional iterator. */ template struct iterator_helper : public JEquals < iterator_helper >, public JForwardIterator< iterator_helper > { typedef std::pair range_type; typedef ordinate_type value_type; typedef JMultiKey multikey_type; typedef JMultiPair multipair_type; /** * Auxiliary class for pair via smart pointer. */ struct pointer_type : private JPair { /** * Constructor. * * \param key key * \param value value */ pointer_type(const key_type key, value_type value) : JPair(key, value) {} /** * Smart pointer operator. * * \return pointer to object */ const JPair* operator->() const { return this; } }; /** * Default constructor. */ iterator_helper() {} /** * Constructor. * * \param __begin begin of data * \param __end end of data */ iterator_helper(iterator_type __begin, iterator_type __end) : range(__begin, __end), i(__begin) {} /** * Smart pointer operator. * * \return pointer to pair of iterators */ pointer_type operator->() { return pointer_type(i->getX(), i->getY()); } /** * Dereference operator. * * \return multidimensional pair */ multipair_type operator*() { return multipair_type(i->getX(), i->getY()); } /** * Equality of super iterator. * * \param cursor super iterator * \return true if equal; else false */ bool equals(const iterator_helper& cursor) const { return i == cursor.i; } /** * Increment super iterator. * * \return true if valid; else false */ virtual bool increment() override { return ++i != range.second; } /** * Get multidimensional key. * * \return key */ multikey_type getKey() const { return multikey_type(i->getX()); } /** * Get value. * * \return value */ value_type getValue() { return i->getY(); } range_type range; iterator_type i; }; public: class super_const_iterator; // forward declaration /** * Terminator class of multidimensional iterator. */ class super_iterator : public iterator_helper { public: friend class JMultiMap; friend class super_const_iterator; /** * Default constructor. */ super_iterator() {} private: /** * Constructor. * * \param __begin begin of data * \param __end end of data */ super_iterator(iterator __begin, iterator __end) : iterator_helper(__begin, __end) {} }; /** * Terminator class of multidimensional const_iterator. */ class super_const_iterator : public iterator_helper, public JEquals { public: friend class JMultiMap; /** * Default constructor. */ super_const_iterator() {} /** * Copy constructor. * * \param cursor super iterator */ super_const_iterator(super_iterator cursor) { this->range = cursor.range; this->i = cursor.i; } /** * Equality of super iterator. * * \param cursor super iterator * \return true if equal; else false */ bool equals(const super_const_iterator& cursor) const { return this->i == cursor.i; } /** * Equality of super iterator. * * \param cursor super iterator * \return true if equal; else false */ bool equals(const super_iterator& cursor) const { return this->i == cursor.i; } private: /** * Constructor. * * \param __begin begin of data * \param __end end of data */ super_const_iterator(const_iterator __begin, const_iterator __end) : iterator_helper(__begin, __end) {} }; class super_const_reverse_iterator; // forward declaration /** * Terminator class of multidimensional reverse iterator. */ class super_reverse_iterator : public iterator_helper { public: friend class JMultiMap; friend class super_const_reverse_iterator; /** * Default constructor. */ super_reverse_iterator() {} private: /** * Constructor. * * \param __begin begin of data * \param __end end of data */ super_reverse_iterator(reverse_iterator __begin, reverse_iterator __end) : iterator_helper(__begin, __end) {} }; /** * Terminator class of multidimensional const_iterator. */ class super_const_reverse_iterator : public iterator_helper, public JEquals { public: friend class JMultiMap; /** * Default constructor. */ super_const_reverse_iterator() {} /** * Copy constructor. * * \param cursor super reverse iterator */ super_const_reverse_iterator(super_reverse_iterator cursor) { this->range = cursor.range; this->i = cursor.i; } /** * Equality of super reverse iterator. * * \param cursor super reverse iterator * \return true if equal; else false */ bool equals(const super_const_reverse_iterator& cursor) const { return this->i == cursor.i; } /** * Equality of super reverse iterator. * * \param cursor super reverse iterator * \return true if equal; else false */ bool equals(const super_reverse_iterator& cursor) const { return this->i == cursor.i; } private: /** * Constructor. * * \param __begin begin of data * \param __end end of data */ super_const_reverse_iterator(const_reverse_iterator __begin, const_reverse_iterator __end) : iterator_helper(__begin, __end) {} }; /** * Get super iterator to begin of data. * * \return super iterator */ super_const_iterator super_begin() const { return super_const_iterator(this->begin(), this->end()); } /** * Get super iterator to reverse begin of data. * * \return super reverse iterator */ super_const_reverse_iterator super_rbegin() const { return super_const_reverse_iterator(this->rbegin(), this->rend()); } /** * Get super iterator to end of data. * * \return super iterator */ super_const_iterator super_end() const { return super_const_iterator(this->end(), this->end()); } /** * Get super iterator to reverse end of data. * * \return super reverse iterator */ super_const_reverse_iterator super_rend() const { return super_const_reverse_iterator(this->rend(), this->rend()); } /** * Get super iterator to begin of data. * * \return super iterator */ super_iterator super_begin() { return super_iterator(this->begin(), this->end()); } /** * Get super iterator to reverse begin of data. * * \return super reverse iterator */ super_reverse_iterator super_rbegin() { return super_reverse_iterator(this->rbegin(), this->rend()); } /** * Get super iterator to end of data. * * \return super iterator */ super_iterator super_end() { return super_iterator(this->end(), this->end()); } /** * Get super iterator to reverse end of data. * * \return super reverse iterator */ super_reverse_iterator super_rend() { return super_reverse_iterator(this->rend(), this->rend()); } /** * Get value. * * \param key multidimensional key * \return value */ ordinate_type& get(const JMultiKey& key) { return get(key.first); } /** * Insert element. * * \param key multidimensional key * \param value value */ void insert(const JMultiKey& key, const ordinate_type& value) { insert(value_type(key.first, value)); } /** * Insert element. * * \param value multidimensional pair */ void insert(const JMultiPair& value) { insert(value_type(value.first, value.second)); } /** * Insert element. * * \param value multidimensional pair */ void insert(const JMultiPair& value) { insert(value_type(value.first, value.second)); } }; } #endif