On Thu, Apr 9, 2009 at 10:19 AM, Kirk, Benjamin (JSC-EG311)
<[email protected]> wrote:
>
> Then there is the fact that the GlobalToLoalMap is derived from a
> std::map...
>
> std::map is very convenient for building up the list, but is not so
> efficient in terms of access or memory requirements.
>
> What I would suggest in this case and can take a hack at instead is that
> GlobalToLocalMap be derived from std::vector.  It seems natural since the
> API provides a vector in the first place.  we then just sort this vector and
> do the lookups with binary searches, which should smoke the map in terms of
> memory and access time performance.

Take a look at my attached pair_vector class.  It's a vector of pairs
which remains unsorted/possibly contains duplicates during insertions.
 (Insertion is O(1)) I've tested it and it uses less memory than
std::map.  You just need to remember to sort() it before you try to
find() anything, and remember that it will happily insert duplicate
entries.  Maybe it would be of use here?

-- 
John
// $Id: pair_vector.h 1117 2008-10-07 22:33:45Z peterson $
#ifndef __pair_vector_h__
#define __pair_vector_h__

#include <cstdlib> // std::abort
#include <vector>
#include <utility> // std::pair
#include <algorithm> // sort, unique
#include <iostream>

/**
 * A version of unsorted_map which uses
 * a single vector which contains <const Key, Value> pairs.
 *
 * @author John W. Peterson, 2008
 */
template <class Key, class Value>
class pair_vector
{
public:
  pair_vector()
    : require_unique(true),
      _sorted(false)
  {}

  ~pair_vector() {}

  typedef std::vector<std::pair<Key, Value> > ContainerType;
  typedef typename ContainerType::iterator iterator;
  typedef typename ContainerType::const_iterator const_iterator;
  typedef std::pair</*const*/Key, Value> value_type;

  std::pair<iterator, bool> insert(const value_type& x)
  {
    _data.push_back(x);

    // We just inserted something, so we're not sorted!
    _sorted = false;
    
    return std::make_pair((++_data.rbegin()).base(), true);
  }

  /**
   * op[] insertion function
   */
  Value& operator[](const Key& k)
  {
    return (*(this->insert(value_type(k, Value()))).first).second;
  }

  /**
   * An object, which can be passed to STL routines, that compares
   * the first entry in either pair.
   */
  struct pair_less_than
  {
    bool operator() (const value_type& v1, const value_type& v2) const
    {
      return v1.first < v2.first;
    }

    bool operator() (const value_type& v1, const Key& k) const
    {
      return v1.first < k;
    }
  };

  struct pair_equal
  {
    bool operator() (const value_type& v1, const value_type& v2) const
    {
      return v1.first == v2.first;
    }
  };
  
  /**
   * Finds an element whose key is k. 
   */
  iterator find(const Key& k) // const
  {
    if (!_sorted)
      {
        // We could sort for you, but chances are if you are calling find on an
        // unsorted_map which has not been sorted, you could be writing bad 
algorithms.
        // So we throw an error.
        std::cout << "Cannot find elements in an unsorted pair_vector.  Call 
sort() first!" << std::endl;
        std::abort();
      }

    iterator result = std::lower_bound(this->begin(), this->end(), k, 
pair_less_than());

    // lower_bound can return the location where a value *would* be
    // inserted if the actual value is not found.  If that happens,
    // then we return the end iterator.
    return (result == this->end() || ( (*result).first > k) ) ?  this->end() : 
result;
  }

  /**
   * Returns an iterator pointing to the beginning of the map.
   */
  iterator begin()
  {
    return _data.begin();
  }

  /**
   * Returns an iterator pointing to the end of the map.
   */
  iterator end()
  {
    return _data.end();
  }

  /**
   * 
--------------------------------------------------------------------------------
   * Additional interfaces not defined by std::map.
   * 
--------------------------------------------------------------------------------
   */

  /**
   * Returns the current _sorted flag.  If true it means
   * the map is currently sorted and searching is allowed.
   * If false, the map is currently not sorted.  Insertion
   * into the map causes it to become unsorted.
   */
  bool sorted() { return _sorted; }

  /**
   * Uses the ability of std::vector to reserve space in an attempt
   * to reduce reallocations while building the container.
   */
  void reserve(unsigned int n)
  {
    _data.reserve(n);
  }

  void sort()
  {
    if (!_sorted)
      {
        std::sort( _data.begin(), _data.end(), pair_less_than() );

        // Remove duplicate entries?
        if (require_unique)
          {
            // This is in keeping with the normal std::map but incurs
            // additional O(N) expense...  Therefore we have this as a
            // user-selectable feature: sometimes we know we're going
            // to insert unique values and we just want them to be
            // quickly searchable...
            iterator new_end = std::unique(this->begin(), this->end(), 
pair_equal());
        
            _data.erase(new_end, _data.end());
          }
        
        _sorted=true;
      }
  }

  /**
   * Do/do not require uniqueness while sorting
   */
  bool require_unique;

  
private:
  bool _sorted;
  ContainerType _data;

  /* Unimplemented */
  pair_vector(const pair_vector& other);
  pair_vector& operator=(const pair_vector& other);
};



#endif // #ifndef __pair_vector_h__
------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Libmesh-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-devel

Reply via email to