Lumiera  0.pre.03
»edit your freedom«
hash-generator-test.cpp
Go to the documentation of this file.
1 /*
2  HashGenerator(Test) - hash value generation details
3 
4  Copyright (C)
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/util.hpp"
21 
22 #include <boost/functional/hash.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <iostream>
25 #include <string>
26 #include <map>
27 
28 using boost::lexical_cast;
29 using util::contains;
30 using std::string;
31 using std::cout;
32 using std::endl;
33 
34 
35 namespace lib {
36 namespace test{
37 
38 
39 
40 
41 
42  /***********************************************************************/
49  class HashGenerator_test : public Test
50  {
51 
52  virtual void
53  run (Arg)
54  {
55  seedRand();
58  }
59 
60 
61  typedef boost::hash<string> BoostStringHasher;
62  typedef std::map<size_t, string> StringsTable;
63 
64 
75  void
77  {
78  BoostStringHasher hashFunction;
79  StringsTable hashValues;
80  string prefix = "Entry.";
81  uint collisions(0);
82  for (uint i=0; i<100000; ++i)
83  {
84  string candidate = prefix + lexical_cast<string> (i);
85  size_t hashVal = hashFunction(candidate);
86 
87  if (contains (hashValues, hashVal))
88  {
89  ++collisions;
90  string other = hashValues[hashVal];
91  cout << "Duplicate at "<< i << endl;
92  cout << "existing--->" << other << endl;
93  cout << "new-------->" << candidate << endl;
94 
95  size_t exHash = hashFunction(other);
96  size_t newHash = hashFunction(candidate);
97  cout << "hash-ex---->" << exHash << endl;
98  cout << "hash_new--->" << newHash << endl;
99  }
100  hashValues[hashVal] = candidate;
101  }
102  if (0 < collisions)
103  cout << "boost::hash for strings produced "<<collisions<<" collisions. This is a known problem."<<endl;
104  else
105  cout << "SURPRISE. No collisions with the boost::hash function." <<endl;
106  }
107 
108 
109 
123  void
125  {
126  StringsTable hashValues;
127  string prefix = "Entry.";
128  const size_t seed = rani();
129 
130  const size_t KNUTH_MAGIC = 2654435761;
131 
132  uint collisions(0);
133  for (uint i=0; i<20000; ++i)
134  {
135  string candidate = prefix + lexical_cast<string> (i);
136  size_t l = candidate.length();
137  size_t hashVal = seed;
138 
139  boost::hash_combine(hashVal, KNUTH_MAGIC * candidate[l-1]);
140  boost::hash_combine(hashVal, KNUTH_MAGIC * candidate[l-2]);
141  boost::hash_combine(hashVal, KNUTH_MAGIC * candidate[l-3]);
142  boost::hash_combine(hashVal, KNUTH_MAGIC * candidate[l-4]);
143  boost::hash_combine(hashVal, candidate);
144 
145  if (contains (hashValues, hashVal))
146  {
147  ++collisions;
148  string other = hashValues[hashVal];
149  cout << "Hash collision between " << i << " and " << other <<endl;
150  }
151  hashValues[hashVal] = candidate;
152  }
153  CHECK (!collisions, "the Knuth trick failed to spread our hash values evenly enough, what a shame...");
154  }
155 
156  };
157 
158 
160  LAUNCHER (HashGenerator_test, "unit common");
161 
162 
163 }} // namespace lib::test
Definition: run.hpp:40
const size_t KNUTH_MAGIC
lousy old tinkerer&#39;s trick: hash values with poor distribution can be improved by spreading the input...
Definition: entry-id.hpp:83
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
Implementation namespace for support and library code.
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255