blob: 55d5d5f800a58f7b229818222050ffeabb12b05d [file] [log] [blame]
tanjent@gmail.comad4b3632010-11-05 01:20:58 +00001//-----------------------------------------------------------------------------
2// Keyset tests generate various sorts of difficult-to-hash keysets and compare
3// the distribution and collision frequency of the hash results against an
4// ideal random distribution
5
6// The sanity checks are also in this cpp/h
7
8#pragma once
9
10#include "Types.h"
11#include "Stats.h"
tanjent@gmail.com2aa29c32011-03-19 08:53:53 +000012#include "Random.h" // for rand_p
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000013
tanjent@gmail.com9d17d0b2010-11-17 04:07:51 +000014#include <algorithm> // for std::swap
tanjent@gmail.com96601f22011-03-31 02:41:29 +000015#include <assert.h>
tanjent@gmail.com9d17d0b2010-11-17 04:07:51 +000016
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000017//-----------------------------------------------------------------------------
18// Sanity tests
19
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000020bool VerificationTest ( pfHash hash, const int hashbits, uint32_t expected, bool verbose );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000021bool SanityTest ( pfHash hash, const int hashbits );
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000022void AppendedZeroesTest ( pfHash hash, const int hashbits );
23
tanjent@gmail.combabb5532011-02-28 06:03:12 +000024//-----------------------------------------------------------------------------
25// Keyset 'Combination' - all possible combinations of input blocks
26
27template< typename hashtype >
28void CombinationKeygenRecurse ( uint32_t * key, int len, int maxlen,
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000029 uint32_t * blocks, int blockcount,
30 pfHash hash, std::vector<hashtype> & hashes )
tanjent@gmail.combabb5532011-02-28 06:03:12 +000031{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000032 if(len == maxlen) return;
tanjent@gmail.combabb5532011-02-28 06:03:12 +000033
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000034 for(int i = 0; i < blockcount; i++)
35 {
36 key[len] = blocks[i];
37
38 //if(len == maxlen-1)
39 {
40 hashtype h;
41 hash(key,(len+1) * sizeof(uint32_t),0,&h);
42 hashes.push_back(h);
43 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +000044
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000045 //else
46 {
47 CombinationKeygenRecurse(key,len+1,maxlen,blocks,blockcount,hash,hashes);
48 }
49 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +000050}
51
52template< typename hashtype >
53bool CombinationKeyTest ( hashfunc<hashtype> hash, int maxlen, uint32_t * blocks, int blockcount, bool testColl, bool testDist, bool drawDiagram )
54{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000055 printf("Keyset 'Combination' - up to %d blocks from a set of %d - ",maxlen,blockcount);
tanjent@gmail.combabb5532011-02-28 06:03:12 +000056
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000057 //----------
tanjent@gmail.combabb5532011-02-28 06:03:12 +000058
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000059 std::vector<hashtype> hashes;
tanjent@gmail.combabb5532011-02-28 06:03:12 +000060
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000061 uint32_t * key = new uint32_t[maxlen];
tanjent@gmail.combabb5532011-02-28 06:03:12 +000062
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000063 CombinationKeygenRecurse<hashtype>(key,0,maxlen,blocks,blockcount,hash,hashes);
tanjent@gmail.combabb5532011-02-28 06:03:12 +000064
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000065 delete [] key;
tanjent@gmail.combabb5532011-02-28 06:03:12 +000066
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000067 printf("%d keys\n",(int)hashes.size());
tanjent@gmail.combabb5532011-02-28 06:03:12 +000068
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000069 //----------
tanjent@gmail.combabb5532011-02-28 06:03:12 +000070
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000071 bool result = true;
tanjent@gmail.combabb5532011-02-28 06:03:12 +000072
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000073 result &= TestHashList<hashtype>(hashes,testColl,testDist,drawDiagram);
74
75 printf("\n");
tanjent@gmail.combabb5532011-02-28 06:03:12 +000076
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000077 return result;
tanjent@gmail.combabb5532011-02-28 06:03:12 +000078}
79
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000080//----------------------------------------------------------------------------
81// Keyset 'Permutation' - given a set of 32-bit blocks, generate keys
82// consisting of all possible permutations of those blocks
83
84template< typename hashtype >
85void PermutationKeygenRecurse ( pfHash hash, uint32_t * blocks, int blockcount, int k, std::vector<hashtype> & hashes )
86{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000087 if(k == blockcount-1)
88 {
89 hashtype h;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000090
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000091 hash(blocks,blockcount * sizeof(uint32_t),0,&h);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000092
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000093 hashes.push_back(h);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000094
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000095 return;
96 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +000097
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000098 for(int i = k; i < blockcount; i++)
99 {
100 std::swap(blocks[k],blocks[i]);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000101
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000102 PermutationKeygenRecurse(hash,blocks,blockcount,k+1,hashes);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000103
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000104 std::swap(blocks[k],blocks[i]);
105 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000106}
107
108template< typename hashtype >
109bool PermutationKeyTest ( hashfunc<hashtype> hash, uint32_t * blocks, int blockcount, bool testColl, bool testDist, bool drawDiagram )
110{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000111 printf("Keyset 'Permutation' - %d blocks - ",blockcount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000112
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000113 //----------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000114
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000115 std::vector<hashtype> hashes;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000116
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000117 PermutationKeygenRecurse<hashtype>(hash,blocks,blockcount,0,hashes);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000118
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000119 printf("%d keys\n",(int)hashes.size());
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000120
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000121 //----------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000122
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000123 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000124
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000125 result &= TestHashList<hashtype>(hashes,testColl,testDist,drawDiagram);
126
127 printf("\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000128
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000129 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000130}
131
132//-----------------------------------------------------------------------------
133// Keyset 'Sparse' - generate all possible N-bit keys with up to K bits set
134
135template < typename keytype, typename hashtype >
136void SparseKeygenRecurse ( pfHash hash, int start, int bitsleft, bool inclusive, keytype & k, std::vector<hashtype> & hashes )
137{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000138 const int nbytes = sizeof(keytype);
139 const int nbits = nbytes * 8;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000140
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000141 hashtype h;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000142
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000143 for(int i = start; i < nbits; i++)
144 {
145 flipbit(&k,nbytes,i);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000146
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000147 if(inclusive || (bitsleft == 1))
148 {
149 hash(&k,sizeof(keytype),0,&h);
150 hashes.push_back(h);
151 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000152
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000153 if(bitsleft > 1)
154 {
155 SparseKeygenRecurse(hash,i+1,bitsleft-1,inclusive,k,hashes);
156 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000157
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000158 flipbit(&k,nbytes,i);
159 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000160}
161
162//----------
163
164template < int keybits, typename hashtype >
165bool SparseKeyTest ( hashfunc<hashtype> hash, const int setbits, bool inclusive, bool testColl, bool testDist, bool drawDiagram )
166{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000167 printf("Keyset 'Sparse' - %d-bit keys with %s %d bits set - ",keybits, inclusive ? "up to" : "exactly", setbits);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000168
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000169 typedef Blob<keybits> keytype;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000170
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000171 std::vector<hashtype> hashes;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000172
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000173 keytype k;
174 memset(&k,0,sizeof(k));
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000175
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000176 if(inclusive)
177 {
178 hashtype h;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000179
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000180 hash(&k,sizeof(keytype),0,&h);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000181
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000182 hashes.push_back(h);
183 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000184
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000185 SparseKeygenRecurse(hash,0,setbits,inclusive,k,hashes);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000186
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000187 printf("%d keys\n",(int)hashes.size());
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000188
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000189 bool result = true;
190
191 result &= TestHashList<hashtype>(hashes,testColl,testDist,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000192
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000193 printf("\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000194
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000195 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000196}
197
198//-----------------------------------------------------------------------------
199// Keyset 'Windows' - for all possible N-bit windows of a K-bit key, generate
200// all possible keys with bits set in that window
201
202template < typename keytype, typename hashtype >
203bool WindowedKeyTest ( hashfunc<hashtype> hash, const int windowbits, bool testCollision, bool testDistribution, bool drawDiagram )
204{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000205 const int keybits = sizeof(keytype) * 8;
206 const int keycount = 1 << windowbits;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000207
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000208 std::vector<hashtype> hashes;
209 hashes.resize(keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000210
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000211 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000212
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000213 int testcount = keybits;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000214
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000215 printf("Keyset 'Windowed' - %3d-bit key, %3d-bit window - %d tests, %d keys per test\n",keybits,windowbits,testcount,keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000216
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000217 for(int j = 0; j <= testcount; j++)
218 {
219 int minbit = j;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000220
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000221 keytype key;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000222
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000223 for(int i = 0; i < keycount; i++)
224 {
225 key = i;
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000226 //key = key << minbit;
227
228 lrot(&key,sizeof(keytype),minbit);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000229
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000230 hash(&key,sizeof(keytype),0,&hashes[i]);
231 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000232
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000233 printf("Window at %3d - ",j);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000234
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000235 result &= TestHashList(hashes,testCollision,testDistribution,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000236
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000237 //printf("\n");
238 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000239
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000240 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000241}
242
243//-----------------------------------------------------------------------------
244// Keyset 'Cyclic' - generate keys that consist solely of N repetitions of M
245// bytes.
246
247// (This keyset type is designed to make MurmurHash2 fail)
248
249template < typename hashtype >
250bool CyclicKeyTest ( pfHash hash, int cycleLen, int cycleReps, const int keycount, bool drawDiagram )
251{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000252 printf("Keyset 'Cyclic' - %d cycles of %d bytes - %d keys\n",cycleReps,cycleLen,keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000253
aappleby@google.com7f20a312011-03-21 20:55:06 +0000254 Rand r(483723);
255
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000256 std::vector<hashtype> hashes;
257 hashes.resize(keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000258
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000259 int keyLen = cycleLen * cycleReps;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000260
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000261 uint8_t * cycle = new uint8_t[cycleLen + 16];
262 uint8_t * key = new uint8_t[keyLen];
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000263
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000264 //----------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000265
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000266 for(int i = 0; i < keycount; i++)
267 {
aappleby@google.com7f20a312011-03-21 20:55:06 +0000268 r.rand_p(cycle,cycleLen);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000269
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000270 *(uint32_t*)cycle = f3mix(i ^ 0x746a94f1);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000271
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000272 for(int j = 0; j < keyLen; j++)
273 {
274 key[j] = cycle[j % cycleLen];
275 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000276
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000277 hash(key,keyLen,0,&hashes[i]);
278 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000279
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000280 //----------
281
282 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000283
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000284 result &= TestHashList(hashes,true,true,drawDiagram);
285 printf("\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000286
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000287 delete [] cycle;
288 delete [] key;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000289
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000290 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000291}
292
293//-----------------------------------------------------------------------------
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000294// Keyset 'TwoBytes' - generate all keys up to length N with two non-zero bytes
295
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000296void TwoBytesKeygen ( int maxlen, KeyCallback & c );
297
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000298template < typename hashtype >
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000299bool TwoBytesTest2 ( pfHash hash, int maxlen, bool drawDiagram )
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000300{
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000301 std::vector<hashtype> hashes;
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000302
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000303 HashCallback<hashtype> c(hash,hashes);
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000304
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000305 TwoBytesKeygen(maxlen,c);
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000306
307 bool result = true;
308
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000309 result &= TestHashList(hashes,true,true,drawDiagram);
tanjent@gmail.com96601f22011-03-31 02:41:29 +0000310 printf("\n");
311
312 return result;
313}
314
315//-----------------------------------------------------------------------------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000316// Keyset 'Text' - generate all keys of the form "prefix"+"core"+"suffix",
317// where "core" consists of all possible combinations of the given character
318// set of length N.
319
320template < typename hashtype >
321bool TextKeyTest ( hashfunc<hashtype> hash, const char * prefix, const char * coreset, const int corelen, const char * suffix, bool drawDiagram )
322{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000323 const int prefixlen = (int)strlen(prefix);
324 const int suffixlen = (int)strlen(suffix);
325 const int corecount = (int)strlen(coreset);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000326
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000327 const int keybytes = prefixlen + corelen + suffixlen;
328 const int keycount = (int)pow(double(corecount),double(corelen));
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000329
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000330 printf("Keyset 'Text' - keys of form \"%s[",prefix);
331 for(int i = 0; i < corelen; i++) printf("X");
332 printf("]%s\" - %d keys\n",suffix,keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000333
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000334 uint8_t * key = new uint8_t[keybytes+1];
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000335
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000336 key[keybytes] = 0;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000337
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000338 memcpy(key,prefix,prefixlen);
339 memcpy(key+prefixlen+corelen,suffix,suffixlen);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000340
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000341 //----------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000342
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000343 std::vector<hashtype> hashes;
344 hashes.resize(keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000345
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000346 for(int i = 0; i < keycount; i++)
347 {
348 int t = i;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000349
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000350 for(int j = 0; j < corelen; j++)
351 {
352 key[prefixlen+j] = coreset[t % corecount]; t /= corecount;
353 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000354
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000355 hash(key,keybytes,0,&hashes[i]);
356 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000357
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000358 //----------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000359
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000360 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000361
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000362 result &= TestHashList(hashes,true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000363
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000364 printf("\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000365
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000366 delete [] key;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000367
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000368 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000369}
370
371//-----------------------------------------------------------------------------
372// Keyset 'Zeroes' - keys consisting of all zeroes, differing only in length
373
374// We reuse one block of empty bytes, otherwise the RAM cost is enormous.
375
376template < typename hashtype >
377bool ZeroKeyTest ( pfHash hash, bool drawDiagram )
378{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000379 int keycount = 64*1024;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000380
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000381 printf("Keyset 'Zeroes' - %d keys\n",keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000382
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000383 unsigned char * nullblock = new unsigned char[keycount];
384 memset(nullblock,0,keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000385
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000386 //----------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000387
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000388 std::vector<hashtype> hashes;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000389
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000390 hashes.resize(keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000391
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000392 for(int i = 0; i < keycount; i++)
393 {
394 hash(nullblock,i,0,&hashes[i]);
395 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000396
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000397 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000398
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000399 result &= TestHashList(hashes,true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000400
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000401 printf("\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000402
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000403 delete [] nullblock;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000404
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000405 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000406}
407
408//-----------------------------------------------------------------------------
409// Keyset 'Seed' - hash "the quick brown fox..." using different seeds
410
411template < typename hashtype >
412bool SeedTest ( pfHash hash, int keycount, bool drawDiagram )
413{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000414 printf("Keyset 'Seed' - %d keys\n",keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000415
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000416 const char * text = "The quick brown fox jumps over the lazy dog";
417 const int len = (int)strlen(text);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000418
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000419 //----------
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000420
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000421 std::vector<hashtype> hashes;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000422
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000423 hashes.resize(keycount);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000424
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000425 for(int i = 0; i < keycount; i++)
426 {
427 hash(text,len,i,&hashes[i]);
428 }
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000429
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000430 bool result = true;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000431
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000432 result &= TestHashList(hashes,true,true,drawDiagram);
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000433
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000434 printf("\n");
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000435
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000436 return result;
tanjent@gmail.comad4b3632010-11-05 01:20:58 +0000437}
438
439//-----------------------------------------------------------------------------