src/work/klao/iter_map.h
author alpar
Mon, 03 Jan 2005 16:19:46 +0000
changeset 1041 9d503ce002db
parent 921 818510fa3d99
permissions -rw-r--r--
- Several convenience maps added to maps.h
- Improvements in doc
klao@347
     1
// -*- c++ -*- //
klao@347
     2
alpar@921
     3
#ifndef LEMON_ITER_MAP
alpar@921
     4
#define LEMON_ITER_MAP
klao@347
     5
klao@347
     6
#include <vector>
klao@347
     7
#include <algorithm>
klao@347
     8
// for uint8_t
klao@347
     9
#include <stdint.h>
klao@347
    10
// for memset
klao@347
    11
#include <cstring>
klao@347
    12
alpar@921
    13
#include <lemon/invalid.h>
klao@347
    14
alpar@921
    15
namespace lemon {
klao@347
    16
klao@367
    17
  /// \brief A map with "small integers" as value set which can enumarate it
klao@367
    18
  /// value classes
klao@347
    19
klao@347
    20
  /// \todo Decide whether we need all the range checkings!!!
klao@347
    21
klao@367
    22
  /// \todo Implement dynamic map behaviour. Is it necessary? Yes it is.
klao@367
    23
klao@361
    24
  template<typename KeyIntMap, uint8_t N, typename Val = uint8_t>
klao@347
    25
  class IterableMap {
klao@347
    26
  public:
klao@347
    27
alpar@987
    28
    typedef typename KeyIntMap::Key Key;
alpar@987
    29
    typedef Val Value;
klao@347
    30
alpar@987
    31
    typedef typename std::vector<Key>::const_iterator iterator;
klao@347
    32
klao@347
    33
  protected:
klao@347
    34
    KeyIntMap &base;
alpar@987
    35
    std::vector<Key> data;
klao@347
    36
    size_t bounds[N];
klao@361
    37
    Val def_val;
klao@347
    38
klao@361
    39
    Val find(size_t a) const {
klao@361
    40
      for(uint8_t n=0; n<N; ++n) {
klao@361
    41
	if(bounds[n] > a)
klao@361
    42
	  return n;
klao@361
    43
      }
klao@361
    44
      return def_val;
klao@347
    45
    }
klao@347
    46
klao@347
    47
    void half_swap(size_t &a, size_t b) {
klao@347
    48
      if(a != b) {
klao@347
    49
	base.set(data[b],a);
klao@347
    50
	data[a] = data[b];
klao@347
    51
	a = b;
klao@347
    52
      }
klao@347
    53
    }
klao@347
    54
klao@347
    55
    size_t move(size_t a, uint8_t m, uint8_t n) {
klao@347
    56
      if(m != n) {
klao@347
    57
	size_t orig_a = a;
alpar@987
    58
	Key orig_key = data[a];
klao@347
    59
	while(m > n) {
klao@347
    60
	  --m;
klao@347
    61
	  half_swap(a, bounds[m]++);
klao@347
    62
	}
klao@362
    63
	// FIXME: range check ide?
klao@347
    64
	while(m < n) {
klao@347
    65
	  half_swap(a, --bounds[m]);
klao@347
    66
	  ++m;
klao@347
    67
	}
klao@347
    68
	if(a != orig_a) {
klao@347
    69
	  base.set(orig_key, a);
klao@347
    70
	  data[a]=orig_key;
klao@347
    71
	}
klao@347
    72
      }
klao@347
    73
      return a;
klao@347
    74
    }
klao@347
    75
klao@347
    76
  public:
klao@347
    77
    
klao@361
    78
    IterableMap(KeyIntMap &_base, Val d = N+1) : base(_base), def_val(d) {
klao@347
    79
      memset(bounds, 0, sizeof(bounds));
klao@347
    80
      //    for(int i=0; i<N; ++i) { bounds[i]=0; }
klao@347
    81
    }
klao@347
    82
alpar@987
    83
    Val operator[](const Key& k) const {
klao@347
    84
      return find(base[k]);
klao@347
    85
    }
klao@347
    86
alpar@987
    87
    void set(const Key& k, Val n) {
klao@362
    88
      // FIXME: range check?
klao@347
    89
      size_t a = base[k];
klao@362
    90
      if(a < bounds[N-1]) {
klao@367
    91
	move(a, find(a), n);
klao@347
    92
      }
klao@362
    93
      else {
klao@362
    94
	insert(k, n);
klao@362
    95
      }
klao@347
    96
    }
klao@347
    97
alpar@987
    98
    void insert(const Key& k, Val n) {
klao@362
    99
      data.push_back(k);
klao@362
   100
      base.set(k, move(bounds[N-1]++, N-1, n));
klao@347
   101
    }
klao@347
   102
klao@367
   103
    /// This func is not very usable, but necessary to implement 
klao@367
   104
    /// dynamic map behaviour.
alpar@987
   105
    void remove(const Key& k) {
klao@367
   106
      size_t a = base[k];
klao@367
   107
      if(a < bounds[N-1]) {
klao@367
   108
	move(a, find(a), N);
klao@367
   109
	data.pop_back();
klao@367
   110
	base.set(k, -1);
klao@367
   111
      }
klao@367
   112
    }
klao@367
   113
klao@361
   114
    iterator begin(Val n) const {
klao@362
   115
      return data.begin() + (n ? bounds[n-1] : 0);
klao@347
   116
    }
klao@347
   117
klao@361
   118
    iterator end(Val n) const {
klao@362
   119
      return data.begin() + bounds[n];
klao@347
   120
    }
klao@347
   121
klao@361
   122
    size_t size(Val n) const {
klao@362
   123
      return bounds[n] - (n ? bounds[n-1] : 0);
klao@347
   124
    }
klao@347
   125
    
klao@347
   126
    size_t size() const {
klao@347
   127
      // assert(bounds[N-1] == data.size());
klao@347
   128
      return bounds[N-1];
klao@347
   129
    }
klao@347
   130
klao@365
   131
klao@365
   132
    /// For use as an iterator...
alpar@987
   133
    Key& first(Key &k, Val n) {
klao@365
   134
      size_t i = (n ? bounds[n-1] : 0);
klao@365
   135
      if( i < bounds[n] ) {
klao@365
   136
	k = data[i];
klao@365
   137
      }
klao@365
   138
      else {
klao@365
   139
	k = INVALID;
klao@365
   140
      }
klao@365
   141
      return k;
klao@365
   142
    }
klao@365
   143
klao@365
   144
    /// For use as an iterator...
alpar@987
   145
    Key& next(Key &k) {
klao@365
   146
      size_t i = base[k];
klao@365
   147
      uint8_t n = find(i);
klao@365
   148
      ++i;
klao@365
   149
      if( i < bounds[n] ) {
klao@365
   150
	k = data[i];
klao@365
   151
      }
klao@365
   152
      else {
klao@365
   153
	k = INVALID;
klao@365
   154
      }
klao@365
   155
      return k;
klao@365
   156
    }
klao@365
   157
klao@347
   158
  };
klao@347
   159
klao@361
   160
klao@361
   161
klao@361
   162
klao@361
   163
  template<typename KeyIntMap>
klao@361
   164
  class IterableBoolMap : public IterableMap<KeyIntMap, 2, bool> {
klao@361
   165
    typedef IterableMap<KeyIntMap, 2, bool> Parent;
klao@361
   166
klao@361
   167
  public:
klao@361
   168
    IterableBoolMap(KeyIntMap &_base, bool d = false) : Parent(_base, d) {}
klao@361
   169
  };
klao@361
   170
klao@347
   171
}
klao@347
   172
#endif