source: git/Singular/CacheImplementation.h @ b08f6fe

spielwiese
Last change on this file since b08f6fe was b08f6fe, checked in by Frank Seelisch <seelisch@…>, 14 years ago
code for extended minor command git-svn-id: file:///usr/local/Singular/svn/trunk@12490 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.8 KB
Line 
1#ifndef CACHE_IMPLEMENTATION_H
2#define CACHE_IMPLEMENTATION_H
3
4template<class KeyClass, class ValueClass>
5Cache<KeyClass, ValueClass>::Cache (const int maxEntries, const int maxWeight) {
6    _maxEntries = maxEntries;
7    _maxWeight = maxWeight;
8    _rank.clear();
9    _key.clear();
10    _value.clear();
11    _weights.clear();
12    _itKey = _key.end(); // referring to past-the-end element in the list
13    _itValue = _value.end(); // referring to past-the-end element in the list
14    _weight = 0;
15}
16
17template<class KeyClass, class ValueClass>
18int Cache<KeyClass, ValueClass>::getWeight() const {
19    return _weight;
20}
21
22template<class KeyClass, class ValueClass>
23int Cache<KeyClass, ValueClass>::getNumberOfEntries() const {
24    return _rank.size();
25}
26
27template<class KeyClass, class ValueClass>
28void Cache<KeyClass, ValueClass>::clear() {
29    _rank.clear();
30    _key.clear();
31    _value.clear();
32    _weights.clear();
33}
34
35template<class KeyClass, class ValueClass>
36Cache<KeyClass, ValueClass>::~Cache() {
37    _rank.clear();
38    _key.clear();
39    _value.clear();
40    _weights.clear();
41}
42
43template<class KeyClass, class ValueClass>
44bool Cache<KeyClass, ValueClass>::hasKey (const KeyClass& key) const {
45    _itKey = _key.end(); // referring to past-the-end element in the list
46    typename list<KeyClass>::const_iterator itKey;
47    _itValue = _value.begin();
48    // As _key is a sorted list, the following could actually be implemented
49    // in logarithmic time, by bisection. For lists this does not work.
50    // But often, we can still terminate the linear loop.
51    for (itKey = _key.begin(); itKey != _key.end(); itKey++) {
52        int c = key.compare(*itKey);
53        if (c == 0) {
54            _itKey = itKey;
55            return true;
56        }
57        if (c == -1) return false;
58        _itValue++;
59    }
60    return false;
61}
62
63template<class KeyClass, class ValueClass>
64ValueClass Cache<KeyClass, ValueClass>::getValue (const KeyClass& key) const {
65    if (_itKey == _key.end())
66        // _itKey refers to past-the-end element in the list
67        // getValue has been called although hasKey produced no match
68        assert(false);
69
70    return *_itValue;
71}
72
73template<class KeyClass, class ValueClass>
74bool Cache<KeyClass, ValueClass>::shrink(const KeyClass& key) {
75    // We need to return true iff the pair with given key needed to be erased
76    // during the shrinking procedure. So far, we assume no:
77    bool result = false;
78    // Shrink until both bounds will be met again:
79    while (int(_key.size()) > _maxEntries || _weight > _maxWeight) {
80        if (deleteLast(key)) result = true;
81    }
82    return result;
83}
84
85template<class KeyClass, class ValueClass>
86int Cache<KeyClass, ValueClass>::getMaxNumberOfEntries() const {
87    return _maxEntries;
88}
89
90template<class KeyClass, class ValueClass>
91int Cache<KeyClass, ValueClass>::getMaxWeight() const {
92    return _maxWeight;
93}
94
95template<class KeyClass, class ValueClass>
96bool Cache<KeyClass, ValueClass>::deleteLast(const KeyClass& key) {
97    if (_rank.size() == 0) {
98        return false; // nothing to do
99    };
100    // We need to do the next empty loop in order to obtain a forward-iterator pointing to the last
101    // entry of _rank.
102    // Note: We cannot use rbegin() because we need the iterator for erasing the last entry which is
103    // only implemented for forward iterators by std::list.
104    list<int>::iterator itRank;
105    for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) { }
106    itRank--;  // Now, this forward iterator points to the last list entry.
107    int deleteIndex = *itRank;   // index of (_key, _value)-pair with worst, i.e., highest _rank
108    bool result = false;
109
110    // now delete entries in _key and _value with index deleteIndex
111    int k = 0;
112    typename list<KeyClass>::iterator itKey;
113    typename list<ValueClass>::iterator itValue = _value.begin();
114    typename list<int>::iterator itWeights = _weights.begin();
115    for (itKey = _key.begin(); itKey != _key.end(); itKey++) {
116        if (k == deleteIndex) {
117            result = (key.compare(*itKey) == 0);
118            break;
119        }
120        itValue++;
121        itWeights++;
122        k++;
123    }
124    _key.erase(itKey);
125    int deleteWeight = *itWeights;
126    _value.erase(itValue);
127    _weights.erase(itWeights);
128
129    // adjust total weight of this cache
130    _weight -= deleteWeight;
131
132    // now delete last entry of _rank and decrement all those indices
133    // in _rank by 1 which were larger than deleteIndex
134    _rank.erase(itRank);
135    for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
136        if (*itRank > deleteIndex) *itRank -= 1;
137    }
138
139    return result;
140}
141
142template<class KeyClass, class ValueClass>
143bool Cache<KeyClass, ValueClass>::put (const KeyClass& key, const ValueClass& value) {
144    bool keyWasContained = false;
145    int oldIndexInKey = -1;
146    int newIndexInKey = _key.size();  // default to enter new (key, value)-pair is at the end of the two lists
147                                      // only used in the case keyWasContained == false
148    int k = 0;
149    typename list<KeyClass>::iterator itKey;
150    typename list<ValueClass>::iterator itOldValue = _value.begin(); // will later only be used in the case keyWasContained == true
151    typename list<int>::iterator itOldWeights = _weights.begin(); // will later only be used in the case keyWasContained == true
152    for (itKey = _key.begin(); itKey != _key.end(); itKey++) {
153        int c = key.compare(*itKey);
154        if (c == -1) {
155            newIndexInKey = k;
156            break;
157        }
158        if (c == 0) {
159            keyWasContained = true;
160            oldIndexInKey = k;
161            break;
162        }
163        itOldValue++;
164        itOldWeights++;
165        k++;
166    }
167    int utility = value.getUtility();
168    int newWeight = value.getWeight();
169    k = 0;
170    typename list<ValueClass>::iterator itValue = _value.begin();
171    for (itValue = _value.begin(); itValue != _value.end(); itValue++) {
172        if (itValue->getUtility() > utility) k++;
173    }
174    int newIndexInRank = k;
175
176    if (keyWasContained) {
177        // There was already a pair of the form (key --> *).
178
179        // adjusting the weight of the cache
180        ValueClass oldValue = *itOldValue;
181        _weight += newWeight - *itOldWeights;
182
183        // overriding old value by argument value
184        itOldValue = _value.erase(itOldValue);
185        itOldWeights = _weights.erase(itOldWeights);
186        ValueClass myValueCopy = value;
187        _value.insert(itOldValue, myValueCopy);
188        _weights.insert(itOldWeights, newWeight);
189
190        int oldIndexInRank = -1;
191        // oldIndexInRank is to be the position in _rank such that
192        // _rank[oldIndexInRank] == oldIndexInKey, i.e.
193        // _key[_rank[oldIndexInRank]] == key:
194        list<int>::iterator itRank;
195        k = 0;
196        for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
197            if (*itRank == oldIndexInKey) {
198                oldIndexInRank = k;
199            }
200            k++;
201        }
202        // Although the key stays the same, the ranking of the (key --> value) pair can be
203        // completely different from before. Thus, we need to repair the entries of _rank:
204        if (oldIndexInRank < newIndexInRank) {  // first insert, then erase
205            k = 0;
206            // insert 'oldIndexInKey' at new position 'newIndexInRank':
207            for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
208                if (k == newIndexInRank) break;
209                k++;
210            }
211            _rank.insert(itRank, oldIndexInKey); // note that this may also insert at position itRank == _rank.end(), i.e.
212                                                 // when above loop did not terminate due to 'break' statement
213            k = 0;
214            // erase 'oldIndexInKey' at old position 'oldIndexInRank':
215            for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
216                if (k == oldIndexInRank) {
217                    _rank.erase(itRank);
218                    break;
219                }
220                k++;
221            }
222        }
223        else {  // oldIndexInRank >= newIndexInRank
224            if (oldIndexInRank > newIndexInRank) { // first erase, then insert
225                k = 0;
226                // erase 'oldIndexInKey' at old position 'oldIndexInRank':
227                for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
228                    if (k == oldIndexInRank) {
229                        _rank.erase(itRank);
230                        break;
231                    }
232                    k++;
233                }
234                k = 0;
235                // insert 'oldIndexInKey' at new position 'newIndexInRank':
236                for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
237                    if (k == newIndexInRank) {
238                        _rank.insert(itRank, oldIndexInKey);
239                        break;
240                    }
241                    k++;
242                }
243            }
244        }
245    }
246    else {
247        // There is no pair of the form (key --> *). We are about to insert a completely new
248        // (key, value)-pair.
249        // After this branch, we shall have _key[newIndexInKey] = key; _value[newIndexInKey] = value.
250        // Note that, after the above computation, newIndexInKey contains the correct target position.
251        // Let's make room for the assignment _rank[newIndexInRank] := newIndexInKey:
252        list<int>::iterator itRank;
253        for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
254            if (newIndexInKey <= *itRank) {
255                *itRank += 1;
256            }
257        }
258        k = 0;
259        for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
260            if (k == newIndexInRank) break;
261            k++;
262        }
263        _rank.insert(itRank, newIndexInKey);
264        // let's insert new key and new value at index newIndexInKey:
265        itValue = _value.begin();
266        typename list<int>::iterator itWeights = _weights.begin();
267        k = 0;
268        for (itKey = _key.begin(); itKey != _key.end(); itKey++) {
269            if (k == newIndexInKey) break;
270            itValue++;
271            itWeights++;
272            k++;
273        }
274        KeyClass myKeyCopy = key;
275        ValueClass myValueCopy = value;
276        _key.insert(itKey, myKeyCopy);
277        _value.insert(itValue, myValueCopy);
278        _weights.insert(itWeights, newWeight);
279        // adjusting the total weight of the cache:
280        _weight += newWeight;
281    };
282    // We may now have to shrink the cache:
283    bool result = shrink(key);  // true iff shrinking deletes the new (key, value)-pair
284
285    assert(_rank.size() == _key.size());
286    assert(_rank.size() == _value.size());
287    return !result; // true iff the new (key --> value) pair is actually in the cache now
288}
289
290template<class KeyClass, class ValueClass>
291string Cache<KeyClass, ValueClass>::toString() const {
292    char h[10];
293    string s = "Cache:";
294    s += "\n   entries: ";
295    sprintf(h, "%d", getNumberOfEntries()); s += h;
296    s += " of at most ";
297    sprintf(h, "%d", getMaxNumberOfEntries()); s += h;
298    s += "\n   weight: ";
299    sprintf(h, "%d", getWeight()); s += h;
300    s += " of at most ";
301    sprintf(h, "%d", getMaxWeight()); s += h;
302    if (_key.size() == 0) {
303        s += "\n   no pairs, i.e. cache is empty";
304    }
305    else {
306        int k = 1;
307        s += "\n   (key --> value) pairs in ascending order of keys:";
308        typename list<KeyClass>::const_iterator itKey;
309        typename list<ValueClass>::const_iterator itValue = _value.begin();
310        for (itKey = _key.begin(); itKey != _key.end(); itKey++) {
311            s += "\n      ";
312            sprintf(h, "%d", k); s += h;
313            s += ". ";
314            s += itKey->toString();
315            s += " --> ";
316            s += itValue->toString();
317            itValue++;
318            k++;
319        }
320        s += "\n   (key --> value) pairs in descending order of ranks:";
321        list<int>::const_iterator itRank;
322        int r = 1;
323        for (itRank = _rank.begin(); itRank != _rank.end(); itRank++) {
324           int index = *itRank;
325           itValue = _value.begin();
326           k = 0;
327           for (itKey = _key.begin(); itKey != _key.end(); itKey++) {
328               if (k == index) break;
329               k++;
330               itValue++;
331           }
332           s += "\n      ";
333           sprintf(h, "%d", r); s += h;
334           s += ". ";
335           s += itKey->toString();
336           s += " --> ";
337           s += itValue->toString();
338           r++;
339        }
340    }
341    return s;
342}
343
344template<class KeyClass, class ValueClass>
345void Cache<KeyClass, ValueClass>::print() const {
346    cout << this->toString();
347}
348
349template<class KeyClass, class ValueClass>
350Cache<KeyClass, ValueClass>::Cache() { }
351
352template<class KeyClass, class ValueClass>
353Cache<KeyClass, ValueClass>::Cache(const Cache& c) {
354    _rank = c._rank;
355    _value = c._value;
356    _weights = c._weights;
357    _key = c._key;
358    _weight = c._weight;
359    _maxEntries = c._maxEntries;
360    _maxWeight = c._maxWeight;
361}
362
363#endif
364/* CACHE_IMPLEMENTATION_H */
Note: See TracBrowser for help on using the repository browser.