Home | History | Annotate | Download | only in src
      1 #pragma once
      2 
      3 #include "Platform.h"
      4 #include "Bitvec.h"
      5 
      6 #include <memory.h>
      7 #include <vector>
      8 #include <map>
      9 #include <set>
     10 
     11 //-----------------------------------------------------------------------------
     12 // If the optimizer detects that a value in a speed test is constant or unused,
     13 // the optimizer may remove references to it or otherwise create code that
     14 // would not occur in a real-world application. To prevent the optimizer from
     15 // doing this we declare two trivial functions that either sink or source data,
     16 // and bar the compiler from optimizing them.
     17 
     18 void     blackhole ( uint32_t x );
     19 uint32_t whitehole ( void );
     20 
     21 //-----------------------------------------------------------------------------
     22 // We want to verify that every test produces the same result on every platform
     23 // To do this, we hash the results of every test to produce an overall
     24 // verification value for the whole test suite. If two runs produce the same
     25 // verification value, then every test in both run produced the same results
     26 
     27 extern uint32_t g_verify;
     28 
     29 // Mix the given blob of data into the verification code
     30 
     31 void MixVCode ( const void * blob, int len );
     32 
     33 
     34 //-----------------------------------------------------------------------------
     35 
     36 typedef void (*pfHash) ( const void * blob, const int len, const uint32_t seed, void * out );
     37 
     38 struct ByteVec : public std::vector<uint8_t>
     39 {
     40   ByteVec ( const void * key, int len )
     41   {
     42     resize(len);
     43     memcpy(&front(),key,len);
     44   }
     45 };
     46 
     47 template< typename hashtype, typename keytype >
     48 struct CollisionMap : public std::map< hashtype, std::vector<keytype> >
     49 {
     50 };
     51 
     52 template< typename hashtype >
     53 struct HashSet : public std::set<hashtype>
     54 {
     55 };
     56 
     57 //-----------------------------------------------------------------------------
     58 
     59 template < class T >
     60 class hashfunc
     61 {
     62 public:
     63 
     64   hashfunc ( pfHash h ) : m_hash(h)
     65   {
     66   }
     67 
     68   inline void operator () ( const void * key, const int len, const uint32_t seed, uint32_t * out )
     69   {
     70     m_hash(key,len,seed,out);
     71   }
     72 
     73   inline operator pfHash ( void ) const
     74   {
     75     return m_hash;
     76   }
     77 
     78   inline T operator () ( const void * key, const int len, const uint32_t seed )
     79   {
     80     T result;
     81 
     82     m_hash(key,len,seed,(uint32_t*)&result);
     83 
     84     return result;
     85   }
     86 
     87   pfHash m_hash;
     88 };
     89 
     90 //-----------------------------------------------------------------------------
     91 // Key-processing callback objects. Simplifies keyset testing a bit.
     92 
     93 struct KeyCallback
     94 {
     95   KeyCallback() : m_count(0)
     96   {
     97   }
     98 
     99   virtual ~KeyCallback()
    100   {
    101   }
    102 
    103   virtual void operator() ( const void * key, int len )
    104   {
    105     m_count++;
    106   }
    107 
    108   virtual void reserve ( int keycount )
    109   {
    110   };
    111 
    112   int m_count;
    113 };
    114 
    115 //----------
    116 
    117 template<typename hashtype>
    118 struct HashCallback : public KeyCallback
    119 {
    120   typedef std::vector<hashtype> hashvec;
    121 
    122   HashCallback ( pfHash hash, hashvec & hashes ) : m_hashes(hashes), m_pfHash(hash)
    123   {
    124     m_hashes.clear();
    125   }
    126 
    127   virtual void operator () ( const void * key, int len )
    128   {
    129     size_t newsize = m_hashes.size() + 1;
    130 
    131     m_hashes.resize(newsize);
    132 
    133     m_pfHash(key,len,0,&m_hashes.back());
    134   }
    135 
    136   virtual void reserve ( int keycount )
    137   {
    138     m_hashes.reserve(keycount);
    139   }
    140 
    141   hashvec & m_hashes;
    142   pfHash m_pfHash;
    143 
    144   //----------
    145 
    146 private:
    147 
    148   HashCallback & operator = ( const HashCallback & );
    149 };
    150 
    151 //----------
    152 
    153 template<typename hashtype>
    154 struct CollisionCallback : public KeyCallback
    155 {
    156   typedef HashSet<hashtype> hashset;
    157   typedef CollisionMap<hashtype,ByteVec> collmap;
    158 
    159   CollisionCallback ( pfHash hash, hashset & collisions, collmap & cmap )
    160   : m_pfHash(hash),
    161     m_collisions(collisions),
    162     m_collmap(cmap)
    163   {
    164   }
    165 
    166   virtual void operator () ( const void * key, int len )
    167   {
    168     hashtype h;
    169 
    170     m_pfHash(key,len,0,&h);
    171 
    172     if(m_collisions.count(h))
    173     {
    174       m_collmap[h].push_back( ByteVec(key,len) );
    175     }
    176   }
    177 
    178   //----------
    179 
    180   pfHash m_pfHash;
    181   hashset & m_collisions;
    182   collmap & m_collmap;
    183 
    184 private:
    185 
    186   CollisionCallback & operator = ( const CollisionCallback & c );
    187 };
    188 
    189 //-----------------------------------------------------------------------------
    190 
    191 template < int _bits >
    192 class Blob
    193 {
    194 public:
    195 
    196   Blob()
    197   {
    198     for(size_t i = 0; i < sizeof(bytes); i++)
    199     {
    200       bytes[i] = 0;
    201     }
    202   }
    203 
    204   Blob ( int x )
    205   {
    206     for(size_t i = 0; i < sizeof(bytes); i++)
    207     {
    208       bytes[i] = 0;
    209     }
    210 
    211     *(int*)bytes = x;
    212   }
    213 
    214   Blob ( const Blob & k )
    215   {
    216     for(size_t i = 0; i < sizeof(bytes); i++)
    217     {
    218       bytes[i] = k.bytes[i];
    219     }
    220   }
    221 
    222   Blob & operator = ( const Blob & k )
    223   {
    224     for(size_t i = 0; i < sizeof(bytes); i++)
    225     {
    226       bytes[i] = k.bytes[i];
    227     }
    228 
    229     return *this;
    230   }
    231 
    232   Blob ( uint64_t a, uint64_t b )
    233   {
    234     uint64_t t[2] = {a,b};
    235     set(&t,16);
    236   }
    237 
    238   void set ( const void * blob, size_t len )
    239   {
    240     const uint8_t * k = (const uint8_t*)blob;
    241 
    242     len = len > sizeof(bytes) ? sizeof(bytes) : len;
    243 
    244     for(size_t i = 0; i < len; i++)
    245     {
    246       bytes[i] = k[i];
    247     }
    248 
    249     for(size_t i = len; i < sizeof(bytes); i++)
    250     {
    251       bytes[i] = 0;
    252     }
    253   }
    254 
    255   uint8_t & operator [] ( int i )
    256   {
    257     return bytes[i];
    258   }
    259 
    260   const uint8_t & operator [] ( int i ) const
    261   {
    262     return bytes[i];
    263   }
    264 
    265   //----------
    266   // boolean operations
    267 
    268   bool operator < ( const Blob & k ) const
    269   {
    270     for(size_t i = 0; i < sizeof(bytes); i++)
    271     {
    272       if(bytes[i] < k.bytes[i]) return true;
    273       if(bytes[i] > k.bytes[i]) return false;
    274     }
    275 
    276     return false;
    277   }
    278 
    279   bool operator == ( const Blob & k ) const
    280   {
    281     for(size_t i = 0; i < sizeof(bytes); i++)
    282     {
    283       if(bytes[i] != k.bytes[i]) return false;
    284     }
    285 
    286     return true;
    287   }
    288 
    289   bool operator != ( const Blob & k ) const
    290   {
    291     return !(*this == k);
    292   }
    293 
    294   //----------
    295   // bitwise operations
    296 
    297   Blob operator ^ ( const Blob & k ) const
    298   {
    299     Blob t;
    300 
    301     for(size_t i = 0; i < sizeof(bytes); i++)
    302     {
    303       t.bytes[i] = bytes[i] ^ k.bytes[i];
    304     }
    305 
    306     return t;
    307   }
    308 
    309   Blob & operator ^= ( const Blob & k )
    310   {
    311     for(size_t i = 0; i < sizeof(bytes); i++)
    312     {
    313       bytes[i] ^= k.bytes[i];
    314     }
    315 
    316     return *this;
    317   }
    318 
    319   int operator & ( int x )
    320   {
    321     return (*(int*)bytes) & x;
    322   }
    323 
    324   Blob & operator &= ( const Blob & k )
    325   {
    326     for(size_t i = 0; i < sizeof(bytes); i++)
    327     {
    328       bytes[i] &= k.bytes[i];
    329     }
    330   }
    331 
    332   Blob operator << ( int c )
    333   {
    334     Blob t = *this;
    335 
    336     lshift(&t.bytes[0],sizeof(bytes),c);
    337 
    338     return t;
    339   }
    340 
    341   Blob operator >> ( int c )
    342   {
    343     Blob t = *this;
    344 
    345     rshift(&t.bytes[0],sizeof(bytes),c);
    346 
    347     return t;
    348   }
    349 
    350   Blob & operator <<= ( int c )
    351   {
    352     lshift(&bytes[0],sizeof(bytes),c);
    353 
    354     return *this;
    355   }
    356 
    357   Blob & operator >>= ( int c )
    358   {
    359     rshift(&bytes[0],sizeof(bytes),c);
    360 
    361     return *this;
    362   }
    363 
    364   //----------
    365 
    366 private:
    367 
    368   uint8_t bytes[(_bits+7)/8];
    369 };
    370 
    371 typedef Blob<128> uint128_t;
    372 typedef Blob<256> uint256_t;
    373 
    374 //-----------------------------------------------------------------------------
    375