mirror of https://github.com/lukechilds/komodo.git
Gavin Andresen
13 years ago
4 changed files with 157 additions and 1 deletions
@ -0,0 +1,63 @@ |
|||
// Copyright (c) 2012 The Bitcoin developers
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
#ifndef BITCOIN_MRUSET_H |
|||
#define BITCOIN_MRUSET_H |
|||
|
|||
#include <set> |
|||
#include <deque> |
|||
|
|||
template <typename T> class mruset |
|||
{ |
|||
public: |
|||
typedef T key_type; |
|||
typedef T value_type; |
|||
typedef typename std::set<T>::iterator iterator; |
|||
typedef typename std::set<T>::const_iterator const_iterator; |
|||
typedef typename std::set<T>::size_type size_type; |
|||
|
|||
protected: |
|||
std::set<T> set; |
|||
std::deque<T> queue; |
|||
size_type nMaxSize; |
|||
|
|||
public: |
|||
mruset(size_type nMaxSizeIn = 0) { nMaxSize = nMaxSizeIn; } |
|||
iterator begin() const { return set.begin(); } |
|||
iterator end() const { return set.end(); } |
|||
size_type size() const { return set.size(); } |
|||
bool empty() const { return set.empty(); } |
|||
iterator find(const key_type& k) const { return set.find(k); } |
|||
size_type count(const key_type& k) const { return set.count(k); } |
|||
bool inline friend operator==(const mruset<T>& a, const mruset<T>& b) { return a.set == b.set; } |
|||
bool inline friend operator==(const mruset<T>& a, const std::set<T>& b) { return a.set == b; } |
|||
bool inline friend operator<(const mruset<T>& a, const mruset<T>& b) { return a.set < b.set; } |
|||
std::pair<iterator, bool> insert(const key_type& x) |
|||
{ |
|||
std::pair<iterator, bool> ret = set.insert(x); |
|||
if (ret.second) |
|||
{ |
|||
if (nMaxSize && queue.size() == nMaxSize) |
|||
{ |
|||
set.erase(queue.front()); |
|||
queue.pop_front(); |
|||
} |
|||
queue.push_back(x); |
|||
} |
|||
return ret; |
|||
} |
|||
size_type max_size() const { return nMaxSize; } |
|||
size_type max_size(size_type s) |
|||
{ |
|||
if (s) |
|||
while (queue.size() >= s) |
|||
{ |
|||
set.erase(queue.front()); |
|||
queue.pop_front(); |
|||
} |
|||
nMaxSize = s; |
|||
return nMaxSize; |
|||
} |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,90 @@ |
|||
#include <boost/test/unit_test.hpp> |
|||
|
|||
using namespace std; |
|||
|
|||
#include "mruset.h" |
|||
#include "util.h" |
|||
|
|||
#define NUM_TESTS 16 |
|||
#define MAX_SIZE 100 |
|||
|
|||
class mrutester |
|||
{ |
|||
private: |
|||
mruset<int> mru; |
|||
std::set<int> set; |
|||
|
|||
public: |
|||
mrutester() { mru.max_size(MAX_SIZE); } |
|||
int size() const { return set.size(); } |
|||
|
|||
void insert(int n) |
|||
{ |
|||
mru.insert(n); |
|||
set.insert(n); |
|||
BOOST_CHECK(mru == set); |
|||
} |
|||
}; |
|||
|
|||
BOOST_AUTO_TEST_SUITE(mruset_tests) |
|||
|
|||
// Test that an mruset behaves like a set, as long as no more than MAX_SIZE elements are in it
|
|||
BOOST_AUTO_TEST_CASE(mruset_like_set) |
|||
{ |
|||
|
|||
for (int nTest=0; nTest<NUM_TESTS; nTest++) |
|||
{ |
|||
mrutester tester; |
|||
while (tester.size() < MAX_SIZE) |
|||
tester.insert(GetRandInt(2 * MAX_SIZE)); |
|||
} |
|||
|
|||
} |
|||
|
|||
// Test that an mruset's size never exceeds its max_size
|
|||
BOOST_AUTO_TEST_CASE(mruset_limited_size) |
|||
{ |
|||
for (int nTest=0; nTest<NUM_TESTS; nTest++) |
|||
{ |
|||
mruset<int> mru(MAX_SIZE); |
|||
for (int nAction=0; nAction<3*MAX_SIZE; nAction++) |
|||
{ |
|||
int n = GetRandInt(2 * MAX_SIZE); |
|||
mru.insert(n); |
|||
BOOST_CHECK(mru.size() <= MAX_SIZE); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 16-bit permutation function
|
|||
int static permute(int n) |
|||
{ |
|||
// hexadecimals of pi; verified to be linearly independent
|
|||
static const int table[16] = {0x243F, 0x6A88, 0x85A3, 0x08D3, 0x1319, 0x8A2E, 0x0370, 0x7344, |
|||
0xA409, 0x3822, 0x299F, 0x31D0, 0x082E, 0xFA98, 0xEC4E, 0x6C89}; |
|||
|
|||
int ret = 0; |
|||
for (int bit=0; bit<16; bit++) |
|||
if (n & (1<<bit)) |
|||
ret ^= table[bit]; |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
// Test that an mruset acts like a moving window, if no duplcate elements are added
|
|||
BOOST_AUTO_TEST_CASE(mruset_window) |
|||
{ |
|||
mruset<int> mru(MAX_SIZE); |
|||
for (int n=0; n<10*MAX_SIZE; n++) |
|||
{ |
|||
mru.insert(permute(n)); |
|||
|
|||
set<int> tester; |
|||
for (int m=max(0,n-MAX_SIZE+1); m<=n; m++) |
|||
tester.insert(permute(m)); |
|||
|
|||
BOOST_CHECK(mru == tester); |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
Loading…
Reference in new issue