Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

compute.h

Go to the documentation of this file.
00001 /* -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
00002 /*********************************************************************
00003  *
00004  * Filename : compute.h (hash)
00005  * C header.
00006  *
00007  * Functions to compute hash values.
00008  *
00009  * This file is a part of the UPPAAL toolkit.
00010  * Copyright (c) 1995 - 2003, Uppsala University and Aalborg University.
00011  * All right reserved.
00012  *
00013  * Not reviewed yet.
00014  * $Id: compute.h,v 1.6 2005/04/22 15:20:10 adavid Exp $
00015  *
00016  **********************************************************************/
00017 
00018 #ifndef INCLUDE_HASH_COMPUTE_H
00019 #define INCLUDE_HASH_COMPUTE_H
00020 
00021 #include <assert.h>
00022 #include <string.h>
00023 #include "base/inttypes.h"
00024 
00025 #ifdef __cplusplus
00026 extern "C" {
00027 #endif
00028 
00029 /**
00030  * Hash mix found at http://burtleburtle.net/bob/hash/
00031  * Original comments from the author:
00032  * --------------------------------------------------------------------
00033  * mix -- mix 3 32-bit values reversibly.
00034  * For every delta with one or two bit set, and the deltas of all three
00035  * high bits or all three low bits, whether the original value of a,b,c
00036  * is almost all zero or is uniformly distributed,
00037  * * If mix() is run forward or backward, at least 32 bits in a,b,c
00038  *   have at least 1/4 probability of changing.
00039  * * If mix() is run forward, every bit of c will change between 1/3 and
00040  *   2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
00041  * mix() takes 36 machine instructions, but only 18 cycles on a superscalar
00042  * machine (like a Pentium or a Sparc).  No faster mixer seems to work,
00043  * that's the result of my brute-force search.  There were about 2^^68
00044  *  hashes to choose from.  I only tested about a billion of those.
00045  * --------------------------------------------------------------------
00046  * NOTE: the hash function based on this hash mix is much faster than
00047  * MD5 hashing and gives exactly the same results.
00048  */
00049 #define HASH_MIX(a,b,c)         \
00050 {                               \
00051   a -= b; a -= c; a ^= (c>>13); \
00052   b -= c; b -= a; b ^= (a<<8);  \
00053   c -= a; c -= b; c ^= (b>>13); \
00054   a -= b; a -= c; a ^= (c>>12); \
00055   b -= c; b -= a; b ^= (a<<16); \
00056   c -= a; c -= b; c ^= (b>>5);  \
00057   a -= b; a -= c; a ^= (c>>3);  \
00058   b -= c; b -= a; b ^= (a<<10); \
00059   c -= a; c -= b; c ^= (b>>15); \
00060 }
00061 
00062 /** Compute hash value for different data types.
00063  * @param data: data to read.
00064  * @param length: number of types to read
00065  * @param initval: used to initialize the hash computation.
00066  * initval is useful when computing a composite hash
00067  * involving different data types. It is then possible
00068  * to chain the hash computation.
00069  * @pre pointers are 32 bits aligned.
00070  * @return: hash value.
00071  * @note the following calls may not necessarily return
00072  * the same result:
00073  * hash_computeU32((uint32_t*)data, 32, initval)
00074  * hash_computeU16((uint16_t*)data, 64, initval)
00075  * hash_computeU8((uint8_t*)data, 128, initval)
00076  */
00077 uint32_t hash_computeU32(const uint32_t *data, size_t length, uint32_t initval);
00078 uint32_t hash_computeU16(const uint16_t *data, size_t length, uint32_t initval);
00079 uint32_t hash_computeU8( const uint8_t  *data, size_t length, uint32_t initval);
00080 
00081 
00082 /** Wrapper functions for convenience.
00083  * Wrap types of input data: support for
00084  * int32_t => uint32_t
00085  * int16_t => uint16_t
00086  * int8_t => uint8_t
00087  * char[] => uint8_t
00088  */
00089 static inline
00090 uint32_t hash_computeI32(const int32_t *data, size_t length, uint32_t initval)
00091 {
00092     return hash_computeU32((uint32_t*)data, length, initval);
00093 }
00094 
00095 static inline
00096 uint32_t hash_computeI16(const int16_t *data, size_t length, uint32_t initval)
00097 {
00098     return hash_computeU16((uint16_t*)data, length, initval);
00099 }
00100 
00101 static inline
00102 uint32_t hash_computeI8(const int8_t  *data, size_t length, uint32_t initval)
00103 {
00104     return hash_computeU8((uint8_t*)data, length, initval);
00105 }
00106 
00107 static inline
00108 uint32_t hash_computeStr(const char *str, uint32_t initval)
00109 {
00110     assert(sizeof(char) == sizeof(uint8_t));
00111     return hash_computeU8((uint8_t*)str, strlen(str), initval);
00112 }
00113 
00114 /** Compute a new hash from 3 previous hash values.
00115  * @param a,b,c: values to combine.
00116  * @return a mixed hashed value.
00117  */
00118 static inline
00119 uint32_t hash_compute(uint32_t a, uint32_t b, uint32_t c)
00120 {
00121     HASH_MIX(a, b, c);
00122     return c;
00123 }
00124 
00125 #ifdef __cplusplus
00126 }
00127 #endif
00128 
00129 #endif // INCLUDE_HASH_COMPUTE_H

Generated on Fri Jun 30 00:03:00 2006 for Module hash by  doxygen 1.4.2