Switched from old hashing functions to use Bob Jenkins' hash routine

- If the underlying type is contiguous, FixedList hashes its storage directly.
- Drop labelPairHash (non-commutative) from fvMeshDistribute since
  FixedList::Hash does the right thing anyhow.
- Hash<edge> specialization is commutative, without multiplication.
- Hash<triFace> specialization kept multiplication (but now uLabel).
  There's not much point optimizing it, since it's not used much anyhow.

Misc. changes

- added StaticAssert to NamedEnum.H
- label.H / uLabel.H : define FOAM_LABEL_MAX, FOAM_ULABEL_MAX with the
  values finally used for the storage.  These can be useful for pre-processor
  checks elsewhere (although I stopped needing them in the meantime).
This commit is contained in:
Mark Olesen
2009-03-04 10:50:14 +01:00
parent 44a86232af
commit 17548296be
28 changed files with 394 additions and 510 deletions

View File

@ -56,6 +56,12 @@ int main(int argc, char *argv[])
Info<< "list:" << list
<< " hash:" << FixedList<label, 4>::Hash<>()(list) << endl;
Info<< "FixedList<label, ..> is contiguous, "
"thus hashing function is irrelevant: with string::hash" << endl;
Info<< "list:" << list
<< " hash:" << FixedList<label, 4>::Hash<string::hash>()(list) << endl;
label a[4] = {0, 1, 2, 3};
FixedList<label, 4> list2(a);

View File

@ -37,7 +37,7 @@ Description
#include "labelList.H"
#include "labelPair.H"
#include "Hashing.H"
#include "Hash.H"
using namespace Foam;
@ -65,64 +65,40 @@ int main(int argc, char *argv[])
forAll(lst, i)
{
unsigned hash1 = Hashing::jenkins(lst[i]);
unsigned hash2 = string::hash()(lst[i]);
unsigned hash1 = string::hash()(lst[i]);
Info<< hex << hash1
<< " (prev " << hash2 << ")"
<< ": " << lst[i] << endl;
Info<< hex << hash1 << ": " << lst[i] << endl;
}
}
else if (listType == "labelList")
{
Info<<"contiguous = " << contiguous<label>() << " "
<< "sizeof(label) " << unsigned(sizeof(label)) << endl << endl;
Info<<"contiguous = " << contiguous<label>() << endl << endl;
labelList lst(is);
unsigned hash4 = 0;
forAll(lst, i)
{
unsigned hash1 = Hashing::intHash(lst[i]);
// direct value
unsigned hash1 = Hash<label>()(lst[i]);
unsigned hash2 = Hashing::jenkins
(
reinterpret_cast<const char*>(&lst[i]),
sizeof(label)
);
unsigned hash3 = Hashing::jenkins
(
reinterpret_cast<const unsigned*>(&lst[i]),
1
);
// incremental
hash4 = Hashing::jenkins
(
reinterpret_cast<const char*>(&lst[i]),
sizeof(label),
hash4
);
// hashed byte-wise
unsigned hash2 = Hash<label>()(lst[i], 0);
Info<< hex << hash1
<< " (alt: " << hash2 << ")"
<< " (alt: " << hash3 << ")"
<< " (incr: " << hash4 << ")"
<< " (seeded: " << hash2 << ")"
<< ": " << dec << lst[i] << endl;
}
if (contiguous<label>())
{
unsigned hash1 = Hashing::jenkins
unsigned hash3 = Hasher
(
lst.cdata(),
lst.size() * sizeof(label)
);
Info<<"contiguous hashed value " << hex << hash1 << endl;
Info<<"contiguous hashed value " << hex << hash3 << endl;
}
}
else if (listType == "labelListList")
@ -131,9 +107,9 @@ int main(int argc, char *argv[])
forAll(lst, i)
{
unsigned hash1 = Hashing::jenkins
unsigned hash1 = Hasher
(
reinterpret_cast<const char*>(lst[i].cdata()),
lst[i].cdata(),
lst[i].size() * sizeof(label)
);

View File

@ -1,6 +1,6 @@
// code taken more-or-less from Paul Hsieh's tests
#include "Hashing.H"
#include "Hasher.H"
#include <stdio.h>
#include <time.h>
@ -692,7 +692,7 @@ uint32_t hashLookup3Orig (const char * k, int length) {
}
uint32_t hashLookup3 (const char * k, int length) {
return Foam::Hashing::jenkins(k, length);
return Foam::Hasher(k, length, 0);
}

View File

@ -52,7 +52,7 @@ $(strings)/fileName/fileNameIO.C
$(strings)/keyType/keyTypeIO.C
$(strings)/wordRe/wordReIO.C
primitives/hashes/Hashing/Hashing.C
primitives/hashes/Hasher/Hasher.C
sha1 = primitives/hashes/SHA1
$(sha1)/SHA1.C

View File

@ -82,8 +82,8 @@ class FixedList
public:
//- Hashing function class
// Rotating hash from http://burtleburtle.net/bob/hash/doobs.html
//- Hashing function class.
// Use Hasher directly for contiguous data. Otherwise hash incrementally.
template< class HashT=Hash<T> >
class Hash
{
@ -91,7 +91,11 @@ public:
Hash()
{}
inline unsigned operator()(const FixedList<T, Size>&) const;
inline unsigned operator()
(
const FixedList<T, Size>&,
unsigned seed = 0
) const;
};
// Static Member Functions

View File

@ -403,26 +403,32 @@ inline bool Foam::FixedList<T, Size>::empty() const
#ifndef __CINT__
// Rotating Hash
template<class T, unsigned Size>
template<class HashT>
inline unsigned Foam::FixedList<T, Size>::Hash<HashT>::operator()
(
const FixedList<T, Size>& lst
const FixedList<T, Size>& lst,
unsigned seed
) const
{
static const unsigned farbit(8*sizeof(label)-4);
unsigned val = Size;
if (contiguous<T>())
{
// hash directly
return Hasher(lst.v_, sizeof(lst.v_), seed);
}
else
{
// hash incrementally
unsigned val = seed;
for (register unsigned i=0; i<Size; i++)
{
val = (val << 4) ^ (val >> farbit) ^ HashT()(lst[i]);
val = HashT()(lst[i], val);
}
return val;
}
}
#endif // __CINT__

View File

@ -37,6 +37,7 @@ SourceFiles
#define NamedEnum_H
#include "HashTable.H"
#include "StaticAssert.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -52,6 +53,9 @@ class NamedEnum
:
public HashTable<int>
{
//- nEnum must be positive (non-zero)
StaticAssert(nEnum > 0);
// Private Member Functions
//- Disallow default bitwise copy construct
@ -99,7 +103,7 @@ public:
return Enum(HashTable<int>::operator[](name));
}
//- Return the name or the given enumeration element
//- Return the name of the given enumeration element
const char* operator[](const Enum e) const
{
return names[e];

View File

@ -133,14 +133,37 @@ public:
};
//- Hash specialization for hashing edges
// Simple commutative hash.
//- Hash specialization for hashing edges - a commutative hash value.
// Hash incrementally.
template<>
inline unsigned Hash<edge>::operator()(const edge& e, unsigned seed) const
{
unsigned val = seed;
if (e[0] < e[1])
{
val = Hash<label>()(e[0], val);
val = Hash<label>()(e[1], val);
}
else
{
val = Hash<label>()(e[1], val);
val = Hash<label>()(e[0], val);
}
return val;
}
//- Hash specialization for hashing edges - a commutative hash value.
// Hash incrementally.
template<>
inline unsigned Hash<edge>::operator()(const edge& e) const
{
return (e[0]*e[1] + e[0]+e[1]);
return Hash<edge>()(e, 0);
}
template<>
inline bool contiguous<edge>() {return true;}

View File

@ -164,14 +164,31 @@ public:
};
//- Hash specialization for hashing triFace
// Simple commutative hash.
//- Hash specialization for hashing triFace - a commutative hash value.
// Hash incrementally.
template<>
inline unsigned Hash<triFace>::operator()(const triFace& t, unsigned seed) const
{
// Fortunately we don't need this very often
const uLabel t0(t[0]);
const uLabel t1(t[1]);
const uLabel t2(t[2]);
const uLabel val = (t0*t1*t2 + t0+t1+t2);
return Hash<uLabel>()(val, seed);
}
//- Hash specialization for hashing triFace - a commutative hash value.
// Hash incrementally.
template<>
inline unsigned Hash<triFace>::operator()(const triFace& t) const
{
return (t[0]*t[1]*t[2] + t[0]+t[1]+t[2]);
return Hash<triFace>::operator()(t, 0);
}
template<>
inline bool contiguous<triFace>() {return true;}

View File

@ -133,7 +133,7 @@ inline Foam::pointField Foam::triFace::points(const pointField& points) const
inline Foam::face Foam::triFace::triFaceFace() const
{
face f(3);
Foam::face f(3);
f[0] = operator[](0);
f[1] = operator[](1);

View File

@ -59,7 +59,7 @@ public:
// Constructors
//- Null constructor for lists
//- Null constructor
inline Pair()
{}
@ -135,6 +135,27 @@ public:
}
//- compare Pairs
// - 0: different
// - +1: identical
// - -1: same pair, but reversed order
static inline int compare(const Pair<Type>& a, const Pair<Type>& b)
{
if (a[0] == b[0] && a[1] == b[1])
{
return 1;
}
else if (a[0] == b[1] && a[1] == b[0])
{
return -1;
}
else
{
return 0;
}
}
// Friend Operators
friend bool operator==(const Pair<Type>& a, const Pair<Type>& b)

View File

@ -34,8 +34,8 @@ namespace Foam
const char* const pTraits<Scalar>::typeName = "scalar";
const Scalar pTraits<Scalar>::zero = 0.0;
const Scalar pTraits<Scalar>::one = 1.0;
const Scalar pTraits<Scalar>::max = ScalarVGREAT;
const Scalar pTraits<Scalar>::min = -ScalarVGREAT;
const Scalar pTraits<Scalar>::max = ScalarVGREAT;
const char* pTraits<Scalar>::componentNames[] = { "x" };
@ -47,11 +47,11 @@ pTraits<Scalar>::pTraits(Istream& is)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
word name(const Scalar s)
word name(const Scalar val)
{
std::ostringstream osBuffer;
osBuffer << s;
return osBuffer.str();
std::ostringstream buf;
buf << val;
return buf.str();
}

View File

@ -39,7 +39,7 @@ Description
Foam::Istream& Foam::operator>>(Istream& is, char& c)
{
is.read(c);
is.check("Istream& operator>>(Istream& is, char& c)");
is.check("Istream& operator>>(Istream&, char&)");
return is;
}

View File

@ -27,7 +27,7 @@ Class
Description
Hash function class for primitives. All non-primitives used to hash
entries on hash tables need a specialized version of this class.
entries on hash tables likely need a specialized version of this class.
\*---------------------------------------------------------------------------*/
@ -36,6 +36,7 @@ Description
#include "label.H"
#include "uLabel.H"
#include "Hasher.H"
#include "pTraits.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -50,15 +51,19 @@ namespace Foam
template<class PrimitiveType>
class Hash
{
public:
Hash()
{}
unsigned operator()(const PrimitiveType& p, unsigned seed) const
{
return Hasher(&p, sizeof(p), seed);
}
unsigned operator()(const PrimitiveType& p) const
{
return unsigned(p);
return Hasher(&p, sizeof(p));
}
};
@ -66,19 +71,53 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Hash specialization for hashing pointer addresses
//- Hash specialization for hashing pointer addresses.
// Treat a pointer like a long.
// This should work for both 32-bit and 64-bit pointers.
template<>
class Hash<void*>
{
public:
Hash()
{}
unsigned operator()(const void* const& p, unsigned seed) const
{
return Hash<long>()(long(p), seed);
}
unsigned operator()(const void* const& p) const
{
return long(p);
return Hash<long>()(long(p));
}
};
//- Hash specialization for hashing labels
template<>
class Hash<Foam::label>
{
public:
Hash()
{}
//- Incrementally hash a label.
// This will necessarily return a different value than the
// non-incremental version.
unsigned operator()(const label& p, unsigned seed) const
{
return Hasher(&p, sizeof(label), seed);
}
//- Return the unsigned representation of a label.
// This helps if people have relied on the hash value corresponding to
// the natural order.
unsigned operator()(const label& p) const
{
return p;
}
};

View File

@ -26,14 +26,16 @@ Description
Hashing functions, mostly from Bob Jenkins
\*---------------------------------------------------------------------------*/
#include "Hashing.H"
#include <cstring>
#include "Hasher.H"
#if defined (__GLIBC__)
# include <endian.h>
#endif
// Left-rotate a 32-bit value and carry by nBits
#define bitRotateLeft(x, nBits) (((x) << (nBits)) | ((x) >> (32 - (nBits))))
// ----------------------------------------------------------------------------
// lookup3.c, by Bob Jenkins, May 2006, Public Domain.
//
@ -68,7 +70,6 @@ Description
// on 1 byte), but shoehorning those bytes into integers efficiently is messy.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// mix -- mix 3 32-bit values reversibly.
//
@ -112,6 +113,17 @@ Description
// rotates.
// ----------------------------------------------------------------------------
#define bitMixer(a, b, c) \
{ \
a -= c; a ^= bitRotateLeft(c, 4); c += b; \
b -= a; b ^= bitRotateLeft(a, 6); a += c; \
c -= b; c ^= bitRotateLeft(b, 8); b += a; \
a -= c; a ^= bitRotateLeft(c,16); c += b; \
b -= a; b ^= bitRotateLeft(a,19); a += c; \
c -= b; c ^= bitRotateLeft(b, 4); b += a; \
}
// ----------------------------------------------------------------------------
// final -- final mixing of 3 32-bit values (a,b,c) into c
//
@ -136,6 +148,18 @@ Description
// 11 8 15 26 3 22 24
// ----------------------------------------------------------------------------
#define bitMixerFinal(a, b, c) \
{ \
c ^= b; c -= bitRotateLeft(b, 14); \
a ^= c; a -= bitRotateLeft(c, 11); \
b ^= a; b -= bitRotateLeft(a, 25); \
c ^= b; c -= bitRotateLeft(b, 16); \
a ^= c; a -= bitRotateLeft(c, 4); \
b ^= a; b -= bitRotateLeft(a, 14); \
c ^= b; c -= bitRotateLeft(b, 24); \
}
// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * * //
// ----------------------------------------------------------------------------
@ -165,11 +189,11 @@ Description
//- specialized little-endian code
#if !defined (__BYTE_ORDER) || (__BYTE_ORDER == __LITTLE_ENDIAN)
static uint32_t jenkins_hashlittle
static unsigned jenkins_hashlittle
(
const void *key,
size_t length,
uint32_t initval
unsigned initval
)
{
uint32_t a, b, c;
@ -343,11 +367,11 @@ static uint32_t jenkins_hashlittle
// ----------------------------------------------------------------------------
// specialized big-endian code
#if !defined (__BYTE_ORDER) || (__BYTE_ORDER == __BIG_ENDIAN)
static uint32_t jenkins_hashbig
static unsigned jenkins_hashbig
(
const void *key,
size_t length,
uint32_t initval
unsigned initval
)
{
uint32_t a, b, c;
@ -447,6 +471,37 @@ static uint32_t jenkins_hashbig
// * * * * * * * * * * * * * * * * Functions * * * * * * * * * * * * * * * * //
unsigned Foam::Hasher
(
const void *key,
size_t length,
unsigned initval
)
{
#ifdef __BYTE_ORDER
# if (__BYTE_ORDER == __BIG_ENDIAN)
return jenkins_hashbig(key, length, initval);
# else
return jenkins_hashlittle(key, length, initval);
# endif
#else
// endian-ness not known at compile-time: runtime endian test
const short endianTest = 0x0100;
// yields 0x01 for big endian
if (*(reinterpret_cast<const char *>(&endianTest)))
{
return jenkins_hashbig(key, length, initval);
}
else
{
return jenkins_hashlittle(key, length, initval);
}
#endif
}
// ----------------------------------------------------------------------------
// This works on all machines. To be useful, it requires
// -- that the key be an array of uint32_t's, and
@ -458,11 +513,11 @@ static uint32_t jenkins_hashbig
// bytes. hashlittle() is more complicated than hashword() only because
// hashlittle() has to dance around fitting the key bytes into registers.
// ----------------------------------------------------------------------------
uint32_t Foam::Hashing::jenkins
unsigned Foam::HasherSingle
(
const uint32_t *k,
size_t length,
uint32_t seed
unsigned seed
)
{
uint32_t a, b, c;
@ -502,12 +557,12 @@ uint32_t Foam::Hashing::jenkins
// both be initialized with seeds. If you pass in (*pb)==0, the output
// (*pc) will be the same as the return value from hashword().
// ----------------------------------------------------------------------------
uint32_t Foam::Hashing::jenkinsTwin
unsigned Foam::HasherDual
(
const uint32_t *k,
size_t length,
uint32_t& hash1, // IN: seed OUT: primary hash value
uint32_t& hash2 // IN: more seed OUT: secondary hash value
unsigned& hash1, // IN: seed OUT: primary hash value
unsigned& hash2 // IN: more seed OUT: secondary hash value
)
{
uint32_t a, b, c;
@ -547,35 +602,4 @@ uint32_t Foam::Hashing::jenkinsTwin
}
uint32_t Foam::Hashing::jenkins
(
const void *key,
size_t length,
uint32_t initval
)
{
#ifdef __BYTE_ORDER
# if (__BYTE_ORDER == __BIG_ENDIAN)
return jenkins_hashbig(key, length, initval);
# else
return jenkins_hashlittle(key, length, initval);
# endif
#else
// endian-ness not known at compile-time: runtime endian test
const short endianTest = 0x0100;
// yields 0x01 for big endian
if (*(reinterpret_cast<const char *>(&endianTest)))
{
return jenkins_hashbig(key, length, initval);
}
else
{
return jenkins_hashlittle(key, length, initval);
}
#endif
}
// ************************************************************************* //

View File

@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Namespace
Foam::Hashing
Description
Misc. hashing functions, mostly from Bob Jenkins.
The Jenkins hashing function(s) is similar in speed to Paul Hsieh's
SuperFast hash, but is public domain, supports incremental hashing
and has been reported to have better characteristics.
It is also what postgresql seems to be using.
SeeAlso
http://burtleburtle.net/bob/c/lookup3.c
SourceFiles
Hasher.C
\*---------------------------------------------------------------------------*/
#ifndef Hasher_H
#define Hasher_H
#include <climits>
#include <cstddef>
#include <stdint.h> // C++0x uses <cstdint>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Bob Jenkins's 96-bit mixer hashing function (lookup3)
// @param[in] data - a character stream
// @param[in] len - the number of bytes
// @param[in] seed - the previous hash, or an arbitrary value
unsigned Hasher(const void* data, size_t len, unsigned seed = 0);
//- An optimized version of Hasher
// @param[in] data - an array of uint32_t values
// @param[in] len - the number of values (not bytes)
// @param[in] seed - the previous hash, or an arbitrary value
unsigned HasherSingle(const uint32_t*, size_t length, unsigned seed = 0);
//- An optimized version of Hasher, returning dual hash values
// @param[in] data - an array of uint32_t values
// @param[in] len - the number of values (not bytes)
// @param[in] hash1 - the previous hash, or an arbitrary value
// on output, the primary hash value
// @param[in] hash1 - the previous hash, or an arbitrary value
// on output, the secondary hash value
unsigned HasherDual
(
const uint32_t*,
size_t len,
unsigned& hash1,
unsigned& hash2
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,321 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Namespace
Foam::Hashing
Description
Misc. hashing functions, mostly from Bob Jenkins.
The Jenkins hashing function(s) is similar in speed to Paul Hsieh's
SuperFast hash, but is public domain, supports incremental hashing
and has been reported to have better characteristics.
It is also what postgresql seems to be using.
SeeAlso
http://burtleburtle.net/bob/c/lookup3.c
SourceFiles
Hashing.C
\*---------------------------------------------------------------------------*/
#ifndef Hashing_H
#define Hashing_H
#include <string>
#include <climits>
#include <cstddef>
#include <stdint.h> // C++0x uses <cstdint>
#include "label.H"
#include "uLabel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Macro defines
/**
* @def bitRotateLeft(val, nBits)
* Left-rotate a 32-bit value and carry by nBits
*/
#define bitRotateLeft(x, nBits) (((x) << (nBits)) | ((x) >> (32 - (nBits))))
/**
* @def bitMixer(a, b, c)
* Mix three 32-bit values reversibly.
*/
#define bitMixer(a, b, c) \
{ \
a -= c; a ^= bitRotateLeft(c, 4); c += b; \
b -= a; b ^= bitRotateLeft(a, 6); a += c; \
c -= b; c ^= bitRotateLeft(b, 8); b += a; \
a -= c; a ^= bitRotateLeft(c,16); c += b; \
b -= a; b ^= bitRotateLeft(a,19); a += c; \
c -= b; c ^= bitRotateLeft(b, 4); b += a; \
}
/**
* @def bitMixerFinal(a, b, c)
* Final mixing of three 32-bit values (a,b,c) into c
*/
#define bitMixerFinal(a, b, c) \
{ \
c ^= b; c -= bitRotateLeft(b, 14); \
a ^= c; a -= bitRotateLeft(c, 11); \
b ^= a; b -= bitRotateLeft(a, 25); \
c ^= b; c -= bitRotateLeft(b, 16); \
a ^= c; a -= bitRotateLeft(c, 4); \
b ^= a; b -= bitRotateLeft(a, 14); \
c ^= b; c -= bitRotateLeft(b, 24); \
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace Hashing
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Bob Jenkins's 96-bit mixer hashing function (lookup3)
// @param[in] data - an array of uint32_t values
// @param[in] len - the number of values (not bytes)
// @param[in] seed - the previous hash, or an arbitrary value
uint32_t jenkins(const uint32_t*, size_t length, uint32_t seed = 0);
//- Bob Jenkins's 96-bit mixer hashing function returning twin hash values
// @param[in] data - an array of uint32_t values
// @param[in] len - the number of values (not bytes)
// @param[in] hash1 - the previous hash, or an arbitrary value
// on output, the primary hash value
// @param[in] hash1 - the previous hash, or an arbitrary value
// on output, the secondary hash value
uint32_t jenkinsTwin
(
const uint32_t*,
size_t len,
uint32_t& hash1,
uint32_t& hash2
);
//- Bob Jenkins's 96-bit mixer hashing function (lookup3)
// @param[in] data - a character stream
// @param[in] len - the number of bytes
// @param[in] seed - the previous hash, or an arbitrary value
uint32_t jenkins(const void* data, size_t len, uint32_t seed = 0);
//- Hashing a C++ string with Jenkins' 96-bit mixer
inline uint32_t jenkins(const std::string& str, uint32_t seed = 0)
{
return jenkins(str.data(), str.size(), seed);
}
//- Hash an unsigned long like two 32bit values
inline uint32_t jenkins(const unsigned long& val)
{
uint32_t a = val >> 32;
uint32_t b = val & 0xFFFFFFFF;
uint32_t c = 0;
bitMixerFinal(a,b,c);
return c;
}
//- Hash a (64-bit) pointer like any long
// Treats bits as zero if the pointer is actually 32bit
inline uint32_t pointerHash(const void* const& p)
{
return jenkins(long(p));
}
#if UINT_MAX > WANTEDURANGE
//- Hash a uLabel
inline unsigned intHash(const uLabel& val1)
{
uint32_t a = val1;
uint32_t b = 0;
uint32_t c = 0;
bitMixerFinal(a,b,c);
return c;
}
//- Hash a uLabel pair
inline unsigned intHash
(
const uLabel& val1,
const uLabel& val2
)
{
uint32_t a = val1;
uint32_t b = val2;
uint32_t c = 0;
bitMixerFinal(a,b,c);
return c;
}
//- Hash a uLabel triplet
inline unsigned intHash
(
const uLabel& val1,
const uLabel& val2,
const uLabel& val3
)
{
uint32_t a = val1;
uint32_t b = val2;
uint32_t c = val3;
bitMixer(a,b,c);
bitMixerFinal(a,b,c);
return c;
}
#else
//- Hash a uLabel
inline unsigned intHash
(
const uLabel& val1
)
{
uint32_t a = val1 >> 32;
uint32_t b = val1 & 0xFFFFFFFF;
uint32_t c = 0;
bitMixerFinal(a,b,c);
return c;
}
//- Hash a uLabel pair
inline unsigned intHash
(
const uLabel& val1,
const uLabel& val2
)
{
uint32_t a = val1 >> 32;
uint32_t b = val1 & 0xFFFFFFFF;
uint32_t c = val2 >> 32;
bitMixer(a,b,c);
a += val2 & 0xFFFFFFFF;
bitMixerFinal(a,b,c);
return c;
}
//- Hash a uLabel triplet
inline unsigned intHash
(
const uLabel& val1,
const uLabel& val2,
const uLabel& val3
)
{
uint32_t a = val1 >> 32;
uint32_t b = val1 & 0xFFFFFFFF;
uint32_t c = val2 >> 32;
bitMixer(a,b,c);
a += val2 & 0xFFFFFFFF;
b += val3 >> 32;
c += val3 & 0xFFFFFFFF;
bitMixerFinal(a,b,c);
return c;
}
#endif
//- Hash a label as uLabel
inline unsigned intHash(const label& val)
{
return intHash(static_cast<uLabel>(val));
}
//- Hash a label pair
inline unsigned intHash
(
const label& val1,
const label& val2
)
{
return intHash
(
static_cast<uLabel>(val1),
static_cast<uLabel>(val2)
);
}
//- Hash a label triplet
inline unsigned intHash
(
const label& val1,
const label& val2,
const label& val3
)
{
return intHash
(
static_cast<uLabel>(val1),
static_cast<uLabel>(val2),
static_cast<uLabel>(val3)
);
}
#if 0
inline unsigned intHashCommutative(const label s1, const label s2)
{
if (s1 < s2)
{
intHash(s1, s2);
}
else
{
intHash(s2, s1);
}
}
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Hashing
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -37,8 +37,8 @@ namespace Foam
const char* const pTraits<label>::typeName = "label";
const label pTraits<label>::zero = 0;
const label pTraits<label>::one = 1;
const label pTraits<label>::max = labelMax;
const label pTraits<label>::min = labelMin;
const label pTraits<label>::max = labelMax;
const char* pTraits<label>::componentNames[] = { "x" };

View File

@ -43,24 +43,27 @@ Description
#if FOAM_LABEL64
# define WANTEDRANGE 9000000000000000000
# define FOAM_LABEL_MAX 9000000000000000000
#else
# define WANTEDRANGE 2000000000
# define FOAM_LABEL_MAX 2000000000
#endif
#if INT_MAX > WANTEDRANGE
#if INT_MAX > FOAM_LABEL_MAX
// Define label as an int
# undef FOAM_LABEL_MAX
# define FOAM_LABEL_MAX INT_MAX
# include "int.H"
namespace Foam
{
typedef int label;
static const label labelMax = INT_MAX;
static const label labelMin = INT_MIN;
static const label labelMax = INT_MAX;
inline label readLabel(Istream& is)
{
@ -70,10 +73,12 @@ namespace Foam
} // End namespace Foam
#elif LONG_MAX > WANTEDRANGE
#elif LONG_MAX > FOAM_LABEL_MAX
// Define label as a long
# undef FOAM_LABEL_MAX
# define FOAM_LABEL_MAX LONG_MAX
# include "int.H"
# include "long.H"
@ -81,8 +86,8 @@ namespace Foam
{
typedef long label;
static const label labelMax = LONG_MAX;
static const label labelMin = LONG_MIN;
static const label labelMax = LONG_MAX;
inline label readLabel(Istream& is)
{
@ -92,10 +97,13 @@ namespace Foam
} // End namespace Foam
#elif LLONG_MAX > WANTEDRANGE
#elif LLONG_MAX > FOAM_LABEL_MAX
// Define label as a long long
# undef FOAM_LABEL_MAX
# define FOAM_LABEL_MAX LLONG_MAX
# include "int.H"
# include "long.H"
# include "longLong.H"
@ -104,8 +112,8 @@ namespace Foam
{
typedef long long label;
static const label labelMax = LLONG_MAX;
static const label labelMin = LLONG_MIN;
static const label labelMax = LLONG_MAX;
inline label readLabel(Istream& is)
{
@ -125,7 +133,7 @@ namespace Foam
namespace Foam
{
// template specialisation for pTraits<label>
//- template specialization for pTraits<label>
template<>
class pTraits<label>
{
@ -151,8 +159,8 @@ public:
static const char* componentNames[];
static const label zero;
static const label one;
static const label max;
static const label min;
static const label max;
// Constructors

View File

@ -37,8 +37,8 @@ namespace Foam
const char* const pTraits<uLabel>::typeName = "uLabel";
const uLabel pTraits<uLabel>::zero = 0;
const uLabel pTraits<uLabel>::one = 1;
const uLabel pTraits<uLabel>::max = uLabelMax;
const uLabel pTraits<uLabel>::min = uLabelMin;
const uLabel pTraits<uLabel>::max = uLabelMax;
const char* pTraits<uLabel>::componentNames[] = { "x" };

View File

@ -43,24 +43,27 @@ SeeAlso
#if FOAM_LABEL64
# define WANTEDURANGE 18000000000000000000
# define FOAM_ULABEL_MAX 18000000000000000000
#else
# define WANTEDURANGE 4000000000
# define FOAM_ULABEL_MAX 4000000000
#endif
#if UINT_MAX > WANTEDURANGE
#if UINT_MAX > FOAM_ULABEL_MAX
// Define uLabel as an unsigned int
# undef FOAM_ULABEL_MAX
# define FOAM_ULABEL_MAX UINT_MAX
# include "uint.H"
namespace Foam
{
typedef unsigned int uLabel;
static const uLabel uLabelMax = UINT_MAX;
static const uLabel uLabelMin = 0;
static const uLabel uLabelMax = UINT_MAX;
inline uLabel readULabel(Istream& is)
{
@ -70,10 +73,13 @@ namespace Foam
} // End namespace Foam
#elif ULONG_MAX > WANTEDURANGE
#elif ULONG_MAX > FOAM_ULABEL_MAX
// Define uLabel as an unsigned long
# undef FOAM_ULABEL_MAX
# define FOAM_ULABEL_MAX ULONG_MAX
# include "uint.H"
# include "ulong.H"
@ -81,8 +87,8 @@ namespace Foam
{
typedef unsigned long uLabel;
static const uLabel uLabelMax = ULONG_MAX;
static const uLabel uLabelMin = 0;
static const uLabel uLabelMax = ULONG_MAX;
inline uLabel readULabel(Istream& is)
{
@ -92,10 +98,12 @@ namespace Foam
} // End namespace Foam
#elif ULLONG_MAX > WANTEDURANGE
#elif ULLONG_MAX > FOAM_ULABEL_MAX
// Define uLabel as an unsigned long long
# undef FOAM_ULABEL_MAX
# error "Not implemented yet"
#endif
@ -109,7 +117,7 @@ namespace Foam
namespace Foam
{
// template specialisation for pTraits<label>
//- template specialization for pTraits<uLabel>
template<>
class pTraits<uLabel>
{

View File

@ -48,7 +48,7 @@ class Ostream;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Return a string representation of an ulong
//- Return a string representation of a ulong
word name(const unsigned long);
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //

View File

@ -45,7 +45,7 @@ Foam::word Foam::name(const unsigned long val)
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, unsigned long& i)
Foam::Istream& Foam::operator>>(Istream& is, unsigned long& val)
{
token t(is);
@ -57,7 +57,7 @@ Foam::Istream& Foam::operator>>(Istream& is, unsigned long& i)
if (t.isLabel())
{
i = static_cast<unsigned long>(t.labelToken());
val = static_cast<unsigned long>(t.labelToken());
}
else
{
@ -85,9 +85,9 @@ unsigned long Foam::readUlong(Istream& is)
}
Foam::Ostream& Foam::operator<<(Ostream& os, const unsigned long i)
Foam::Ostream& Foam::operator<<(Ostream& os, const unsigned long val)
{
os.write(label(i));
os.write(label(val));
os.check("Ostream& operator<<(Ostream&, const unsigned long)");
return os;
}

View File

@ -47,6 +47,7 @@ SourceFiles
#define string_H
#include "char.H"
#include "Hasher.H"
#include <string>
#include <cstring>
@ -92,7 +93,7 @@ public:
hash()
{}
inline unsigned operator()(const string&) const;
inline unsigned operator()(const string&, unsigned seed = 0) const;
};

View File

@ -198,19 +198,11 @@ inline Foam::string Foam::string::operator()(const size_type n) const
inline unsigned Foam::string::hash::operator()
(
const string& key
const string& key,
unsigned seed
) const
{
const size_type len = key.length();
const char *data = key.data();
register unsigned val = 0;
for (register size_type i=0; i < len; ++data, ++i)
{
val = (val << 1) ^ *data;
}
return val;
return Hasher(key.data(), key.size(), seed);
}
// ************************************************************************* //

View File

@ -864,7 +864,7 @@ void Foam::fvMeshDistribute::findCouples
{
// Store domain neighbour as map so we can easily look for pair
// with same face+proc.
HashTable<label, labelPair, labelPairHash> map(domainFace.size());
HashTable<label, labelPair, labelPair::Hash<> > map(domainFace.size());
forAll(domainFace, bFaceI)
{
@ -884,8 +884,8 @@ void Foam::fvMeshDistribute::findCouples
{
labelPair myData(sourceFace[bFaceI], sourceProc[bFaceI]);
HashTable<label, labelPair, labelPairHash>::const_iterator iter =
map.find(myData);
HashTable<label, labelPair, labelPair::Hash<> >::const_iterator
iter = map.find(myData);
if (iter != map.end())
{

View File

@ -106,23 +106,6 @@ class fvMeshDistribute
}
};
//- Hash labelPair.
// Note non-commutative since p[0] is face, p[1] is processor.
class labelPairHash
{
public:
labelPairHash()
{}
unsigned operator()(const labelPair& p) const
{
uLabel p0 = static_cast<uLabel>(p[0]);
uLabel p1 = static_cast<uLabel>(p[1]);
return (p0*p0 + p0+p1);
}
};
// Private Member Functions