#include <algorithm>
#include <iterator>
#include <vector>
template<class iterator> auto structure_dereference_operator(const iterator& r) -> typename std::iterator_traits<iterator>::pointer {return r.operator->();}
template<class type> typename std::iterator_traits<type*>::pointer structure_dereference_operator(const type*& r) {return r;}
template <class key_,
class mapped_,
class traits_ = std::less<key_>,
class undertype_ = std::vector<std::pair<key_,mapped_> >
>
class associative
{
public:
typedef traits_ key_compare;
typedef key_ key_type;
typedef mapped_ mapped_type;
typedef std::pair<const key_type, mapped_type> value_type;
typedef typename undertype_::allocator_type allocator_type;
typedef typename allocator_type::template rebind<value_type>::other value_allocator_type;
typedef typename undertype_::const_iterator const_iterator;
class value_compare {
key_compare pred_;
public:
inline value_compare(key_compare pred=key_compare()) : pred_(pred) {}
inline bool operator()(const value_type& left, const value_type& right) const {return pred_(left.first,right.first);}
inline bool operator()(const value_type& left, const key_type& right) const {return pred_(left.first,right);}
inline bool operator()(const key_type& left, const value_type& right) const {return pred_(left,right.first);}
inline bool operator()(const key_type& left, const key_type& right) const {return pred_(left,right);}
inline key_compare key_comp( ) const {return pred_;}
};
class iterator {
public:
typedef typename value_allocator_type::difference_type difference_type;
typedef typename value_allocator_type::value_type value_type;
typedef typename value_allocator_type::reference reference;
typedef typename value_allocator_type::pointer pointer;
typedef std::bidirectional_iterator_tag iterator_category;
inline iterator(const typename undertype_::iterator& rhs) : data(rhs) {}
inline pointer operator->() const {return reinterpret_cast<pointer>(structure_dereference_operator(data));}
operator const_iterator&() const {return data;}
protected:
typename undertype_::iterator data;
};
template<class input_iterator>
inline associative(input_iterator first, input_iterator last) : internal_(first, last), comp_()
{if (std::is_sorted(internal_.begin(), internal_.end())==false) std::sort(internal_.begin(), internal_.end(), comp_);}
inline iterator find(const key_type& key) {return std::lower_bound(internal_.begin(), internal_.end(), key, comp_);}
inline const_iterator find(const key_type& key) const {return std::lower_bound(internal_.begin(), internal_.end(), key, comp_);}
protected:
undertype_ internal_;
value_compare comp_;
};
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#ifdef _DEBUG
#define WARMUP_TIME_MILLISECONDS 1
#define TEST_TIME_MILLISECONDS 9
#else
#define WARMUP_TIME_MILLISECONDS 10
#define TEST_TIME_MILLISECONDS 400
#endif
template<unsigned int size>
struct payload {
int data[size/4];
payload() {data[0]=rand()*RAND_MAX+rand();}
bool operator==(const payload& rhs) const {return data[0]==rhs.data[0];}
bool operator<(const payload& rhs) const {return data[0]<rhs.data[0];}
};
template<class load, class container>
void test_internal(const std::vector<std::pair<load, load>>& data, const char* classname, const char* payloadname) {
clock_t beg,end,elapsed,freq;
unsigned int count=0;
bool timed=false;
freq = CLOCKS_PER_SEC;
std::vector<std::pair<load, load>> shuffled(data.begin(), data.end());
std::random_shuffle(shuffled.begin(), shuffled.end());
std::vector<std::pair<load, load>> sorted(data.begin(), data.end());
std::sort(sorted.begin(), sorted.end());
std::cout << payloadname << ' ' << std::setw(4) << data.size() << ' ' << classname << ' ';
timed = false;
elapsed = 0;
{
container a(data.begin(), data.end());
do {
beg = clock();
auto i=a.find(shuffled[count%data.size()].first);
end = clock();
elapsed += end-beg;
if (elapsed>WARMUP_TIME_MILLISECONDS && !timed) {
elapsed =0;
count=0;
timed = true;
}
++count;
} while(elapsed<TEST_TIME_MILLISECONDS);
}
std::cout << std::setw(9) << count << '\n';
}
template<class load>
void test(const std::vector<std::pair<load, load>> &data, const char* payload_name) {
std::vector<std::pair<load, load>> use(data.begin(), data.begin()+8);
for( ; ; ) {
test_internal<load, std::map <load,load>>(use, "std::map", payload_name);
test_internal<load, associative<load,load,std::less<load>,std::vector<std::pair<load,load>>>>(use, "astv/vec", payload_name);
if (use.size()<1024)
use.insert(use.end(), data.begin()+use.size()*1ull, data.begin()+use.size()*2ull);
else if (use.size() != data.size())
use.insert(use.end(), data.begin()+use.size(), data.end());
else break;
}
}
int main() {
test(std::vector<std::pair<payload< 4>,payload< 4>>>(2000), "payload< 4>");
test(std::vector<std::pair<payload< 8>,payload< 8>>>(2000), "payload< 8>");
test(std::vector<std::pair<payload< 16>,payload< 16>>>(2000), "payload< 16>");
test(std::vector<std::pair<payload< 32>,payload< 32>>>(2000), "payload< 32>");
test(std::vector<std::pair<payload< 64>,payload< 64>>>(2000), "payload< 64>");
test(std::vector<std::pair<payload<128>,payload<128>>>(2000), "payload<128>");
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGl0ZXJhdG9yPgojaW5jbHVkZSA8dmVjdG9yPgoKdGVtcGxhdGU8Y2xhc3MgaXRlcmF0b3I+IGF1dG8gc3RydWN0dXJlX2RlcmVmZXJlbmNlX29wZXJhdG9yKGNvbnN0IGl0ZXJhdG9yJiByKSAtPiB0eXBlbmFtZSBzdGQ6Oml0ZXJhdG9yX3RyYWl0czxpdGVyYXRvcj46OnBvaW50ZXIge3JldHVybiByLm9wZXJhdG9yLT4oKTt9CnRlbXBsYXRlPGNsYXNzIHR5cGU+IHR5cGVuYW1lIHN0ZDo6aXRlcmF0b3JfdHJhaXRzPHR5cGUqPjo6cG9pbnRlciBzdHJ1Y3R1cmVfZGVyZWZlcmVuY2Vfb3BlcmF0b3IoY29uc3QgdHlwZSomIHIpIHtyZXR1cm4gcjt9Cgp0ZW1wbGF0ZSA8Y2xhc3Mga2V5XywgCiAgICAgICAgICBjbGFzcyBtYXBwZWRfLCAKICAgICAgICAgIGNsYXNzIHRyYWl0c18gPSBzdGQ6Omxlc3M8a2V5Xz4sCgkJICBjbGFzcyB1bmRlcnR5cGVfID0gc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPGtleV8sbWFwcGVkXz4gPgogICAgICAgICA+CmNsYXNzIGFzc29jaWF0aXZlCnsKcHVibGljOgoJdHlwZWRlZiB0cmFpdHNfIGtleV9jb21wYXJlOwoJdHlwZWRlZiBrZXlfIGtleV90eXBlOwoJdHlwZWRlZiBtYXBwZWRfIG1hcHBlZF90eXBlOwoJdHlwZWRlZiBzdGQ6OnBhaXI8Y29uc3Qga2V5X3R5cGUsIG1hcHBlZF90eXBlPiB2YWx1ZV90eXBlOwoJdHlwZWRlZiB0eXBlbmFtZSB1bmRlcnR5cGVfOjphbGxvY2F0b3JfdHlwZSBhbGxvY2F0b3JfdHlwZTsKCXR5cGVkZWYgdHlwZW5hbWUgYWxsb2NhdG9yX3R5cGU6OnRlbXBsYXRlIHJlYmluZDx2YWx1ZV90eXBlPjo6b3RoZXIgdmFsdWVfYWxsb2NhdG9yX3R5cGU7Cgl0eXBlZGVmIHR5cGVuYW1lIHVuZGVydHlwZV86OmNvbnN0X2l0ZXJhdG9yIGNvbnN0X2l0ZXJhdG9yOwoKCWNsYXNzIHZhbHVlX2NvbXBhcmUgewoJCWtleV9jb21wYXJlIHByZWRfOwoJcHVibGljOgoJCWlubGluZSB2YWx1ZV9jb21wYXJlKGtleV9jb21wYXJlIHByZWQ9a2V5X2NvbXBhcmUoKSkgOiBwcmVkXyhwcmVkKSB7fQoJCWlubGluZSBib29sIG9wZXJhdG9yKCkoY29uc3QgdmFsdWVfdHlwZSYgbGVmdCwgY29uc3QgdmFsdWVfdHlwZSYgcmlnaHQpIGNvbnN0IHtyZXR1cm4gcHJlZF8obGVmdC5maXJzdCxyaWdodC5maXJzdCk7fQoJCWlubGluZSBib29sIG9wZXJhdG9yKCkoY29uc3QgdmFsdWVfdHlwZSYgbGVmdCwgY29uc3Qga2V5X3R5cGUmIHJpZ2h0KSBjb25zdCB7cmV0dXJuIHByZWRfKGxlZnQuZmlyc3QscmlnaHQpO30KCQlpbmxpbmUgYm9vbCBvcGVyYXRvcigpKGNvbnN0IGtleV90eXBlJiBsZWZ0LCBjb25zdCB2YWx1ZV90eXBlJiByaWdodCkgY29uc3Qge3JldHVybiBwcmVkXyhsZWZ0LHJpZ2h0LmZpcnN0KTt9CgkJaW5saW5lIGJvb2wgb3BlcmF0b3IoKShjb25zdCBrZXlfdHlwZSYgbGVmdCwgY29uc3Qga2V5X3R5cGUmIHJpZ2h0KSBjb25zdCB7cmV0dXJuIHByZWRfKGxlZnQscmlnaHQpO30KCQlpbmxpbmUga2V5X2NvbXBhcmUga2V5X2NvbXAoICkgY29uc3Qge3JldHVybiBwcmVkXzt9Cgl9OwoJY2xhc3MgaXRlcmF0b3IgIHsKCXB1YmxpYzogICAgICAgCgkJdHlwZWRlZiB0eXBlbmFtZSB2YWx1ZV9hbGxvY2F0b3JfdHlwZTo6ZGlmZmVyZW5jZV90eXBlIGRpZmZlcmVuY2VfdHlwZTsKCQl0eXBlZGVmIHR5cGVuYW1lIHZhbHVlX2FsbG9jYXRvcl90eXBlOjp2YWx1ZV90eXBlIHZhbHVlX3R5cGU7CgkJdHlwZWRlZiB0eXBlbmFtZSB2YWx1ZV9hbGxvY2F0b3JfdHlwZTo6cmVmZXJlbmNlIHJlZmVyZW5jZTsKCQl0eXBlZGVmIHR5cGVuYW1lIHZhbHVlX2FsbG9jYXRvcl90eXBlOjpwb2ludGVyIHBvaW50ZXI7CgkJdHlwZWRlZiBzdGQ6OmJpZGlyZWN0aW9uYWxfaXRlcmF0b3JfdGFnIGl0ZXJhdG9yX2NhdGVnb3J5OwoJCWlubGluZSBpdGVyYXRvcihjb25zdCB0eXBlbmFtZSB1bmRlcnR5cGVfOjppdGVyYXRvciYgcmhzKSA6IGRhdGEocmhzKSB7fQoJCWlubGluZSBwb2ludGVyIG9wZXJhdG9yLT4oKSBjb25zdCB7cmV0dXJuIHJlaW50ZXJwcmV0X2Nhc3Q8cG9pbnRlcj4oc3RydWN0dXJlX2RlcmVmZXJlbmNlX29wZXJhdG9yKGRhdGEpKTt9CgkJb3BlcmF0b3IgY29uc3RfaXRlcmF0b3ImKCkgY29uc3Qge3JldHVybiBkYXRhO30KCXByb3RlY3RlZDoKCQl0eXBlbmFtZSB1bmRlcnR5cGVfOjppdGVyYXRvciBkYXRhOwoJfTsKCiAgICB0ZW1wbGF0ZTxjbGFzcyBpbnB1dF9pdGVyYXRvcj4KICAgIGlubGluZSBhc3NvY2lhdGl2ZShpbnB1dF9pdGVyYXRvciBmaXJzdCwgaW5wdXRfaXRlcmF0b3IgbGFzdCkgOiBpbnRlcm5hbF8oZmlyc3QsIGxhc3QpLCBjb21wXygpIAoJe2lmIChzdGQ6OmlzX3NvcnRlZChpbnRlcm5hbF8uYmVnaW4oKSwgaW50ZXJuYWxfLmVuZCgpKT09ZmFsc2UpIHN0ZDo6c29ydChpbnRlcm5hbF8uYmVnaW4oKSwgaW50ZXJuYWxfLmVuZCgpLCBjb21wXyk7fQoKCWlubGluZSBpdGVyYXRvciBmaW5kKGNvbnN0IGtleV90eXBlJiBrZXkpIHtyZXR1cm4gc3RkOjpsb3dlcl9ib3VuZChpbnRlcm5hbF8uYmVnaW4oKSwgaW50ZXJuYWxfLmVuZCgpLCBrZXksIGNvbXBfKTt9CiAgICBpbmxpbmUgY29uc3RfaXRlcmF0b3IgZmluZChjb25zdCBrZXlfdHlwZSYga2V5KSBjb25zdCB7cmV0dXJuIHN0ZDo6bG93ZXJfYm91bmQoaW50ZXJuYWxfLmJlZ2luKCksIGludGVybmFsXy5lbmQoKSwga2V5LCBjb21wXyk7fQoKcHJvdGVjdGVkOgoJdW5kZXJ0eXBlXyBpbnRlcm5hbF87Cgl2YWx1ZV9jb21wYXJlIGNvbXBfOwp9OwoKI2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDxjdGltZT4KI2luY2x1ZGUgPGZzdHJlYW0+CiNpbmNsdWRlIDxpb21hbmlwPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxtYXA+CgojaWZkZWYgX0RFQlVHCiNkZWZpbmUgV0FSTVVQX1RJTUVfTUlMTElTRUNPTkRTIDEKI2RlZmluZSBURVNUX1RJTUVfTUlMTElTRUNPTkRTIDkKI2Vsc2UKI2RlZmluZSBXQVJNVVBfVElNRV9NSUxMSVNFQ09ORFMgMTAKI2RlZmluZSBURVNUX1RJTUVfTUlMTElTRUNPTkRTIDQwMAojZW5kaWYKCnRlbXBsYXRlPHVuc2lnbmVkIGludCBzaXplPgpzdHJ1Y3QgcGF5bG9hZCB7CglpbnQgZGF0YVtzaXplLzRdOwoJcGF5bG9hZCgpIHtkYXRhWzBdPXJhbmQoKSpSQU5EX01BWCtyYW5kKCk7fQoJYm9vbCBvcGVyYXRvcj09KGNvbnN0IHBheWxvYWQmIHJocykgY29uc3Qge3JldHVybiBkYXRhWzBdPT1yaHMuZGF0YVswXTt9Cglib29sIG9wZXJhdG9yPChjb25zdCBwYXlsb2FkJiByaHMpIGNvbnN0IHtyZXR1cm4gZGF0YVswXTxyaHMuZGF0YVswXTt9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBsb2FkLCBjbGFzcyBjb250YWluZXI+CnZvaWQgdGVzdF9pbnRlcm5hbChjb25zdCBzdGQ6OnZlY3RvcjxzdGQ6OnBhaXI8bG9hZCwgbG9hZD4+JiBkYXRhLCBjb25zdCBjaGFyKiBjbGFzc25hbWUsIGNvbnN0IGNoYXIqIHBheWxvYWRuYW1lKSB7CgljbG9ja190IGJlZyxlbmQsZWxhcHNlZCxmcmVxOwoJdW5zaWduZWQgaW50IGNvdW50PTA7Cglib29sIHRpbWVkPWZhbHNlOwoJZnJlcSA9IENMT0NLU19QRVJfU0VDOwoKCXN0ZDo6dmVjdG9yPHN0ZDo6cGFpcjxsb2FkLCBsb2FkPj4gc2h1ZmZsZWQoZGF0YS5iZWdpbigpLCBkYXRhLmVuZCgpKTsKCXN0ZDo6cmFuZG9tX3NodWZmbGUoc2h1ZmZsZWQuYmVnaW4oKSwgc2h1ZmZsZWQuZW5kKCkpOwoJc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPGxvYWQsIGxvYWQ+PiBzb3J0ZWQoZGF0YS5iZWdpbigpLCBkYXRhLmVuZCgpKTsKCXN0ZDo6c29ydChzb3J0ZWQuYmVnaW4oKSwgc29ydGVkLmVuZCgpKTsKCQoJc3RkOjpjb3V0IDw8IHBheWxvYWRuYW1lIDw8ICcgJyA8PCBzdGQ6OnNldHcoNCkgPDwgZGF0YS5zaXplKCkgPDwgJyAnIDw8IGNsYXNzbmFtZSA8PCAnICc7Cgl0aW1lZCA9IGZhbHNlOwoJZWxhcHNlZCA9IDA7Cgl7CgkgICAgY29udGFpbmVyIGEoZGF0YS5iZWdpbigpLCBkYXRhLmVuZCgpKTsKCQlkbyB7CgkJCWJlZyA9IGNsb2NrKCk7CgkJCWF1dG8gaT1hLmZpbmQoc2h1ZmZsZWRbY291bnQlZGF0YS5zaXplKCldLmZpcnN0KTsKCQkJZW5kID0gY2xvY2soKTsKCQkJZWxhcHNlZCArPSBlbmQtYmVnOwogICAJCQlpZiAoZWxhcHNlZD5XQVJNVVBfVElNRV9NSUxMSVNFQ09ORFMgJiYgIXRpbWVkKSB7CgkJCQllbGFwc2VkID0wOwoJCQkJY291bnQ9MDsKCQkJCXRpbWVkID0gdHJ1ZTsKCQkJfQoJCQkrK2NvdW50OwoJCX0gd2hpbGUoZWxhcHNlZDxURVNUX1RJTUVfTUlMTElTRUNPTkRTKTsKCX0KCXN0ZDo6Y291dCA8PCBzdGQ6OnNldHcoOSkgPDwgY291bnQgPDwgJ1xuJzsKfQoKdGVtcGxhdGU8Y2xhc3MgbG9hZD4Kdm9pZCB0ZXN0KGNvbnN0IHN0ZDo6dmVjdG9yPHN0ZDo6cGFpcjxsb2FkLCBsb2FkPj4gJmRhdGEsIGNvbnN0IGNoYXIqIHBheWxvYWRfbmFtZSkgewoJc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPGxvYWQsIGxvYWQ+PiB1c2UoZGF0YS5iZWdpbigpLCBkYXRhLmJlZ2luKCkrOCk7Cglmb3IoIDsgOyApIHsKCQl0ZXN0X2ludGVybmFsPGxvYWQsIHN0ZDo6bWFwICAgPGxvYWQsbG9hZD4+KHVzZSwgInN0ZDo6bWFwIiwgcGF5bG9hZF9uYW1lKTsKCQl0ZXN0X2ludGVybmFsPGxvYWQsIGFzc29jaWF0aXZlPGxvYWQsbG9hZCxzdGQ6Omxlc3M8bG9hZD4sc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPGxvYWQsbG9hZD4+Pj4odXNlLCAiYXN0di92ZWMiLCBwYXlsb2FkX25hbWUpOwoJCWlmICh1c2Uuc2l6ZSgpPDEwMjQpCgkJCXVzZS5pbnNlcnQodXNlLmVuZCgpLCBkYXRhLmJlZ2luKCkrdXNlLnNpemUoKSoxdWxsLCBkYXRhLmJlZ2luKCkrdXNlLnNpemUoKSoydWxsKTsKCQllbHNlIGlmICh1c2Uuc2l6ZSgpICE9IGRhdGEuc2l6ZSgpKQoJCQl1c2UuaW5zZXJ0KHVzZS5lbmQoKSwgZGF0YS5iZWdpbigpK3VzZS5zaXplKCksIGRhdGEuZW5kKCkpOwoJCWVsc2UgYnJlYWs7Cgl9Cn0KCmludCBtYWluKCkgewoJdGVzdChzdGQ6OnZlY3RvcjxzdGQ6OnBhaXI8cGF5bG9hZDwgIDQ+LHBheWxvYWQ8ICA0Pj4+KDIwMDApLCAicGF5bG9hZDwgIDQ+Iik7Cgl0ZXN0KHN0ZDo6dmVjdG9yPHN0ZDo6cGFpcjxwYXlsb2FkPCAgOD4scGF5bG9hZDwgIDg+Pj4oMjAwMCksICJwYXlsb2FkPCAgOD4iKTsKCXRlc3Qoc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPHBheWxvYWQ8IDE2PixwYXlsb2FkPCAxNj4+PigyMDAwKSwgInBheWxvYWQ8IDE2PiIpOwoJdGVzdChzdGQ6OnZlY3RvcjxzdGQ6OnBhaXI8cGF5bG9hZDwgMzI+LHBheWxvYWQ8IDMyPj4+KDIwMDApLCAicGF5bG9hZDwgMzI+Iik7Cgl0ZXN0KHN0ZDo6dmVjdG9yPHN0ZDo6cGFpcjxwYXlsb2FkPCA2ND4scGF5bG9hZDwgNjQ+Pj4oMjAwMCksICJwYXlsb2FkPCA2ND4iKTsKCXRlc3Qoc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPHBheWxvYWQ8MTI4PixwYXlsb2FkPDEyOD4+PigyMDAwKSwgInBheWxvYWQ8MTI4PiIpOwoKCXJldHVybiAwOwp9Cg==