Add hash goodies, and name::hash()
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
f7e59366ea
commit
f71fdea42e
5 changed files with 104 additions and 1 deletions
|
@ -1 +1 @@
|
|||
add_library(util trace.cpp debug.cpp name.cpp exception.cpp verbosity.cpp interrupt.cpp)
|
||||
add_library(util trace.cpp debug.cpp name.cpp exception.cpp verbosity.cpp interrupt.cpp hash.cpp)
|
||||
|
|
63
src/util/hash.cpp
Normal file
63
src/util/hash.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
namespace lean {
|
||||
|
||||
void mix(unsigned & a, unsigned & b, unsigned & c) {
|
||||
a -= b; a -= c; a ^= (c>>13);
|
||||
b -= c; b -= a; b ^= (a<<8);
|
||||
c -= a; c -= b; c ^= (b>>13);
|
||||
a -= b; a -= c; a ^= (c>>12);
|
||||
b -= c; b -= a; b ^= (a<<16);
|
||||
c -= a; c -= b; c ^= (b>>5);
|
||||
a -= b; a -= c; a ^= (c>>3);
|
||||
b -= c; b -= a; b ^= (a<<10);
|
||||
c -= a; c -= b; c ^= (b>>15);
|
||||
}
|
||||
|
||||
// Bob Jenkin's hash function.
|
||||
// http://burtleburtle.net/bob/hash/doobs.html
|
||||
unsigned hash(char const * str, unsigned length, unsigned init_value) {
|
||||
register unsigned a, b, c, len;
|
||||
|
||||
/* Set up the internal state */
|
||||
len = length;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
c = init_value; /* the previous hash value */
|
||||
|
||||
/*---------------------------------------- handle most of the key */
|
||||
while (len >= 12) {
|
||||
a += reinterpret_cast<unsigned const *>(str)[0];
|
||||
b += reinterpret_cast<unsigned const *>(str)[1];
|
||||
c += reinterpret_cast<unsigned const *>(str)[2];
|
||||
mix(a,b,c);
|
||||
str += 12; len -= 12;
|
||||
}
|
||||
|
||||
/*------------------------------------- handle the last 11 bytes */
|
||||
c += length;
|
||||
switch(len) {
|
||||
/* all the case statements fall through */
|
||||
case 11: c+=((unsigned)str[10]<<24);
|
||||
case 10: c+=((unsigned)str[9]<<16);
|
||||
case 9 : c+=((unsigned)str[8]<<8);
|
||||
/* the first byte of c is reserved for the length */
|
||||
case 8 : b+=((unsigned)str[7]<<24);
|
||||
case 7 : b+=((unsigned)str[6]<<16);
|
||||
case 6 : b+=((unsigned)str[5]<<8);
|
||||
case 5 : b+=str[4];
|
||||
case 4 : a+=((unsigned)str[3]<<24);
|
||||
case 3 : a+=((unsigned)str[2]<<16);
|
||||
case 2 : a+=((unsigned)str[1]<<8);
|
||||
case 1 : a+=str[0];
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
mix(a,b,c);
|
||||
/*-------------------------------------------- report the result */
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
20
src/util/hash.h
Normal file
20
src/util/hash.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace lean {
|
||||
|
||||
unsigned hash(char const * str, unsigned length, unsigned init_value);
|
||||
|
||||
inline unsigned hash(unsigned h1, unsigned h2) {
|
||||
h2 -= h1; h2 ^= (h1 << 8);
|
||||
h1 -= h2; h2 ^= (h1 << 16);
|
||||
h2 -= h1; h2 ^= (h1 << 10);
|
||||
return h2;
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@ Author: Leonardo de Moura
|
|||
#include "name.h"
|
||||
#include "debug.h"
|
||||
#include "rc.h"
|
||||
#include "hash.h"
|
||||
|
||||
namespace lean {
|
||||
|
||||
|
@ -209,6 +210,24 @@ size_t name::size(char const * sep) const {
|
|||
}
|
||||
}
|
||||
|
||||
unsigned name::hash() const {
|
||||
if (m_imp == nullptr)
|
||||
return 17;
|
||||
else {
|
||||
unsigned h = 13;
|
||||
imp const * i = m_imp;
|
||||
do {
|
||||
if (i->m_is_string)
|
||||
h = ::lean::hash(i->m_str, strlen(i->m_str), h);
|
||||
else
|
||||
h = ::lean::hash(h, i->m_k);
|
||||
i = i->m_prefix;
|
||||
}
|
||||
while (i != nullptr);
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, name const & n) {
|
||||
name::imp::display(out, default_name_separator, n.m_imp);
|
||||
return out;
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
\brief Size of the this name (in characters) when using the given separator.
|
||||
*/
|
||||
size_t size(char const * sep = default_name_separator) const;
|
||||
unsigned hash() const;
|
||||
friend std::ostream & operator<<(std::ostream & out, name const & n);
|
||||
class sep {
|
||||
name const & m_name;
|
||||
|
|
Loading…
Reference in a new issue