, . , .
, get.h, , .
, got.h, , , STL .
, main.cpp, , .
#include <cstddef>
using std::size_t;
template < typename C >
typename C::value_type get ( C const &container, size_t lo, size_t hi )
{
typedef typename C::value_type item;
static unsigned const bits = (unsigned)sizeof(item)*8u;
static size_t const mask = ~(size_t)0u/bits*bits;
size_t lo_adr = (lo ) / bits;
size_t hi_adr = (hi-(hi>0)) / bits;
unsigned hi_shift = (unsigned)(mask-hi)%bits;
item hi_val = container[hi_adr] << hi_shift >> hi_shift;
unsigned lo_shift = (unsigned)lo%bits;
if ( hi_adr <= lo_adr ) return (hi_val>>lo_shift) * (lo<hi);
return ( hi_val<<bits-lo_shift | container[lo_adr]>>lo_shift );
}
, get.h , , STL- . , 32- 128- . unsigned , size_t. , - lo , get() . .
#include <cstddef>
using std::size_t;
template < typename val_type >
val_type shiftr(val_type val, size_t n)
{
val_type good = n < sizeof(val_type)*8;
return good * (val >> (n * good));
}
template < typename val_type >
val_type shiftl(val_type val, size_t n)
{
val_type good = n < sizeof(val_type)*8;
return good * (val << (n * good));
}
template < typename val_type >
val_type lowbits(val_type val, size_t n)
{
val_type mask = shiftr<val_type>((val_type)(-1), sizeof(val_type)*8 - n);
return val & mask;
}
struct range_location_t {
size_t lindex;
size_t hindex;
size_t lbegin;
size_t llen;
size_t hlen;
};
template < typename val_type >
range_location_t locate(size_t begin, size_t end)
{
size_t lindex = begin / (sizeof(val_type)*8);
size_t hindex = end / (sizeof(val_type)*8);
size_t lbegin = begin % (sizeof(val_type)*8);
size_t hend = end % (sizeof(val_type)*8);
size_t len = (end - begin) * size_t(begin <= end);
size_t hlen = hend * (hindex > lindex);
size_t llen = len - hlen;
range_location_t l = { lindex, hindex, lbegin, llen, hlen };
return l;
}
template < typename C >
typename C::value_type got ( C const&container, size_t begin, size_t end )
{
typedef typename C::value_type val_type;
range_location_t loc = locate<val_type>(begin, end);
val_type low = lowbits<val_type>(container[loc.lindex] >> loc.lbegin, loc.llen);
val_type high = shiftl<val_type>(lowbits<val_type>(container[loc.hindex], loc.hlen), loc.llen);
return high | low;
}
, got.h , , , STL- . get.h, , , , .
#include <vector>
#include <cstddef>
#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "get.h"
#include "got.h"
template < typename Container > class Test {
typedef typename Container::value_type val_type;
typedef val_type (*fun_type) ( Container const &, size_t, size_t );
typedef void (Test::*fun_test) ( unsigned, unsigned );
static unsigned const total_bits = 256;
static unsigned const entry_bits = (unsigned)sizeof(val_type)*8u;
Container _container;
fun_type _function;
bool _failed;
void get_value ( unsigned lo, unsigned hi ) {
_function(_container,lo,hi);
_function(_container,lo,hi);
_function(_container,lo,hi);
_function(_container,lo,hi);
_function(_container,lo,hi);
_function(_container,lo,hi);
_function(_container,lo,hi);
_function(_container,lo,hi);
}
void verify ( unsigned lo, unsigned hi ) {
val_type value = _function(_container,lo,hi);
if ( lo < hi ) {
for ( unsigned i=lo; i<hi; i++ ) {
val_type val = _container[i/entry_bits] >> i%entry_bits & 1u;
if ( val != (value&1u) ) {
printf("lo=%d hi=%d [%d] is'nt %d\n",lo,hi,i,(unsigned)val);
_failed = true;
}
value >>= 1u;
}
}
if ( value ) {
printf("lo=%d hi=%d value contains high bits set to 1\n",lo,hi);
_failed = true;
}
}
void run ( fun_test fun ) {
for ( unsigned lo=0; lo<total_bits; lo++ ) {
unsigned h0 = 0;
if ( lo > entry_bits ) h0 = lo - (entry_bits+1);
unsigned h1 = lo+64;
if ( h1 > total_bits ) h1 = total_bits;
for ( unsigned hi=h0; hi<=h1; hi++ ) {
(this->*fun)(lo,hi);
}
}
}
static uint64_t time_used ( ) {
struct rusage ru;
getrusage(RUSAGE_THREAD,&ru);
struct timeval t = ru.ru_utime;
return (uint64_t) t.tv_sec*1000 + t.tv_usec/1000;
}
public:
Test ( fun_type function ): _function(function), _failed() {
val_type entry;
unsigned index = 0;
unsigned value = 0;
static char const entropy[] = "The quick brown Fox jumps over the lazy Dog";
do {
if ( ! (index%entry_bits) ) entry = 0;
entry <<= 1;
entry |= value ^= 1u & entropy[index/7%sizeof(entropy)] >> index%7;
++index;
if ( ! (index%entry_bits) ) _container.push_back(entry);
} while ( index < total_bits );
}
bool correctness() {
_failed = false;
run(&Test::verify);
return !_failed;
}
void performance() {
uint64_t t1 = time_used();
for ( unsigned i=0; i<999; i++ ) run(&Test::get_value);
uint64_t t2 = time_used();
printf("used %d ms\n",(unsigned)(t2-t1));
}
void operator() ( char const * name ) {
printf("testing %s\n",name);
correctness();
performance();
}
};
int main()
{
typedef typename std::vector<uint64_t> Container;
Test<Container> test(get<Container>); test("get");
Test<Container> tost(got<Container>); tost("got");
}
, main.cpp , get.h got.h, , . . , 256 , , , , . , , .