CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/CondFormats/Common/src/hash64.cc

Go to the documentation of this file.
00001 #include "CondFormats/Common/interface/hash64.h"
00002 
00003 /*
00004 --------------------------------------------------------------------
00005 mix -- mix 3 64-bit values reversibly.
00006 mix() takes 48 machine instructions, but only 24 cycles on a superscalar
00007   machine (like Intel's new MMX architecture).  It requires 4 64-bit
00008   registers for 4::2 parallelism.
00009 All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of
00010   (a,b,c), and all deltas of bottom bits were tested.  All deltas were
00011   tested both on random keys and on keys that were nearly all zero.
00012   These deltas all cause every bit of c to change between 1/3 and 2/3
00013   of the time (well, only 113/400 to 287/400 of the time for some
00014   2-bit delta).  These deltas all cause at least 80 bits to change
00015   among (a,b,c) when the mix is run either forward or backward (yes it
00016   is reversible).
00017 This implies that a hash using mix64 has no funnels.  There may be
00018   characteristics with 3-bit deltas or bigger, I didn't test for
00019   those.
00020 --------------------------------------------------------------------
00021 */
00022 #define mix64(a,b,c) \
00023 { \
00024   a -= b; a -= c; a ^= (c>>43); \
00025   b -= c; b -= a; b ^= (a<<9); \
00026   c -= a; c -= b; c ^= (b>>8); \
00027   a -= b; a -= c; a ^= (c>>38); \
00028   b -= c; b -= a; b ^= (a<<23); \
00029   c -= a; c -= b; c ^= (b>>5); \
00030   a -= b; a -= c; a ^= (c>>35); \
00031   b -= c; b -= a; b ^= (a<<49); \
00032   c -= a; c -= b; c ^= (b>>11); \
00033   a -= b; a -= c; a ^= (c>>12); \
00034   b -= c; b -= a; b ^= (a<<18); \
00035   c -= a; c -= b; c ^= (b>>22); \
00036 }
00037 
00038 typedef  unsigned long  long ub8;   /* unsigned 8-byte quantities */
00039 typedef  unsigned long  int  ub4;   /* unsigned 4-byte quantities */
00040 typedef  unsigned       char ub1;
00041 
00042 
00043 namespace cond {
00044 
00045   ub8 hash64( ub1 * k, ub8 length, ub8 level)
00046   // register ub1 *k;        /* the key */
00047   // register ub8  length;   /* the length of the key */
00048   // register ub8  level;    /* the previous hash, or an arbitrary value */
00049   {
00050     register ub8 a,b,c,len;
00051     
00052     /* Set up the internal state */
00053     len = length;
00054     a = b = level;                         /* the previous hash value */
00055     c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */
00056     
00057     /*---------------------------------------- handle most of the key */
00058     if (((unsigned long)k)&7)
00059       {
00060         while (len >= 24)
00061           {
00062             a += (k[0]        +((ub8)k[ 1]<< 8)+((ub8)k[ 2]<<16)+((ub8)k[ 3]<<24)
00063                   +((ub8)k[4 ]<<32)+((ub8)k[ 5]<<40)+((ub8)k[ 6]<<48)+((ub8)k[ 7]<<56));
00064             b += (k[8]        +((ub8)k[ 9]<< 8)+((ub8)k[10]<<16)+((ub8)k[11]<<24)
00065                   +((ub8)k[12]<<32)+((ub8)k[13]<<40)+((ub8)k[14]<<48)+((ub8)k[15]<<56));
00066             c += (k[16]       +((ub8)k[17]<< 8)+((ub8)k[18]<<16)+((ub8)k[19]<<24)
00067                   +((ub8)k[20]<<32)+((ub8)k[21]<<40)+((ub8)k[22]<<48)+((ub8)k[23]<<56));
00068             mix64(a,b,c);
00069             k += 24; len -= 24;
00070           }
00071       }
00072     else
00073       {
00074         while (len >= 24)    /* aligned */
00075           {
00076             a += *(ub8 *)(k+0);
00077             b += *(ub8 *)(k+8);
00078             c += *(ub8 *)(k+16);
00079             mix64(a,b,c);
00080             k += 24; len -= 24;
00081           }
00082       }
00083     
00084     /*------------------------------------- handle the last 23 bytes */
00085     c += length;
00086     switch(len)              /* all the case statements fall through */
00087       {
00088       case 23: c+=((ub8)k[22]<<56);
00089       case 22: c+=((ub8)k[21]<<48);
00090       case 21: c+=((ub8)k[20]<<40);
00091       case 20: c+=((ub8)k[19]<<32);
00092       case 19: c+=((ub8)k[18]<<24);
00093       case 18: c+=((ub8)k[17]<<16);
00094       case 17: c+=((ub8)k[16]<<8);
00095         /* the first byte of c is reserved for the length */
00096       case 16: b+=((ub8)k[15]<<56);
00097       case 15: b+=((ub8)k[14]<<48);
00098       case 14: b+=((ub8)k[13]<<40);
00099       case 13: b+=((ub8)k[12]<<32);
00100       case 12: b+=((ub8)k[11]<<24);
00101       case 11: b+=((ub8)k[10]<<16);
00102       case 10: b+=((ub8)k[ 9]<<8);
00103       case  9: b+=((ub8)k[ 8]);
00104       case  8: a+=((ub8)k[ 7]<<56);
00105       case  7: a+=((ub8)k[ 6]<<48);
00106       case  6: a+=((ub8)k[ 5]<<40);
00107       case  5: a+=((ub8)k[ 4]<<32);
00108       case  4: a+=((ub8)k[ 3]<<24);
00109       case  3: a+=((ub8)k[ 2]<<16);
00110       case  2: a+=((ub8)k[ 1]<<8);
00111       case  1: a+=((ub8)k[ 0]);
00112         /* case 0: nothing left to add */
00113       }
00114     mix64(a,b,c);
00115     /*-------------------------------------------- report the result */
00116     return c;
00117   }
00118   
00119   
00120 }