172 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			172 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*  $Id$
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Part of SWI-Prolog
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Author:	Austin Appleby
							 | 
						||
| 
								 | 
							
								    License:	Public domain
							 | 
						||
| 
								 | 
							
								    See:	http://murmurhash.googlepages.com/
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <SWI-Prolog.h>			/* het uintptr_t */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
							 | 
						||
| 
								 | 
							
								The first one is actually  MurmurHashNeutral2().   It  produces the same
							 | 
						||
| 
								 | 
							
								hash  as  MurmurHashAligned2()  on  little    endian  machines,  but  is
							 | 
						||
| 
								 | 
							
								significantly  slower.  MurmurHashAligned2()  however    is   broken  on
							 | 
						||
| 
								 | 
							
								big-endian machines, as it produces different   hashes, depending on the
							 | 
						||
| 
								 | 
							
								alignment. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								NOTE: This file is a copy of src/pl-hash.c from SWI-Prolog.
							 | 
						||
| 
								 | 
							
								- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if WORDS_BIGENDIAN
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								unsigned int
							 | 
						||
| 
								 | 
							
								rdf_murmer_hash(const void * key, int len, unsigned int seed)
							 | 
						||
| 
								 | 
							
								{ const unsigned int m = 0x5bd1e995;
							 | 
						||
| 
								 | 
							
								  const int r = 24;
							 | 
						||
| 
								 | 
							
								  unsigned int h = seed ^ len;
							 | 
						||
| 
								 | 
							
								  const unsigned char * data = (const unsigned char *)key;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while( len >= 4 )
							 | 
						||
| 
								 | 
							
								  { unsigned int k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    k  = data[0];
							 | 
						||
| 
								 | 
							
								    k |= data[1] << 8;
							 | 
						||
| 
								 | 
							
								    k |= data[2] << 16;
							 | 
						||
| 
								 | 
							
								    k |= data[3] << 24;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    k *= m;
							 | 
						||
| 
								 | 
							
								    k ^= k >> r;
							 | 
						||
| 
								 | 
							
								    k *= m;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    h *= m;
							 | 
						||
| 
								 | 
							
								    h ^= k;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    data += 4;
							 | 
						||
| 
								 | 
							
								    len -= 4;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch( len )
							 | 
						||
| 
								 | 
							
								  { case 3: h ^= data[2] << 16;
							 | 
						||
| 
								 | 
							
								    case 2: h ^= data[1] << 8;
							 | 
						||
| 
								 | 
							
								    case 1: h ^= data[0];
							 | 
						||
| 
								 | 
							
								      h *= m;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  h ^= h >> 13;
							 | 
						||
| 
								 | 
							
								  h *= m;
							 | 
						||
| 
								 | 
							
								  h ^= h >> 15;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return h;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else /*WORDS_BIGENDIAN*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								unsigned int
							 | 
						||
| 
								 | 
							
								rdf_murmer_hash(const void *key, int len, unsigned int seed)
							 | 
						||
| 
								 | 
							
								{ const unsigned int m = 0x5bd1e995;
							 | 
						||
| 
								 | 
							
								  const int r = 24;
							 | 
						||
| 
								 | 
							
								  const unsigned char * data = (const unsigned char *)key;
							 | 
						||
| 
								 | 
							
								  unsigned int h = seed ^ len;
							 | 
						||
| 
								 | 
							
								  int align = (int)(uintptr_t)data & 3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( align && (len >= 4) )
							 | 
						||
| 
								 | 
							
								  { unsigned int t = 0, d = 0;
							 | 
						||
| 
								 | 
							
								    int sl, sr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch( align )
							 | 
						||
| 
								 | 
							
								    { case 1: t |= data[2] << 16;
							 | 
						||
| 
								 | 
							
								      case 2: t |= data[1] << 8;
							 | 
						||
| 
								 | 
							
								      case 3: t |= data[0];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    t <<= (8 * align);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    data += 4-align;
							 | 
						||
| 
								 | 
							
								    len -= 4-align;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sl = 8 * (4-align);
							 | 
						||
| 
								 | 
							
								    sr = 8 * align;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while ( len >= 4 )
							 | 
						||
| 
								 | 
							
								    { unsigned int k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      d = *(unsigned int *)data;
							 | 
						||
| 
								 | 
							
								      t = (t >> sr) | (d << sl);
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      k = t;
							 | 
						||
| 
								 | 
							
								      MIX(h,k,m);
							 | 
						||
| 
								 | 
							
								      t = d;
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      data += 4;
							 | 
						||
| 
								 | 
							
								      len -= 4;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    d = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( len >= align )
							 | 
						||
| 
								 | 
							
								    { unsigned int k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      switch( align )
							 | 
						||
| 
								 | 
							
								      { case 3: d |= data[2] << 16;
							 | 
						||
| 
								 | 
							
									case 2: d |= data[1] << 8;
							 | 
						||
| 
								 | 
							
									case 1: d |= data[0];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      k = (t >> sr) | (d << sl);
							 | 
						||
| 
								 | 
							
								      MIX(h,k,m);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      data += align;
							 | 
						||
| 
								 | 
							
								      len -= align;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      switch(len)
							 | 
						||
| 
								 | 
							
								      { case 3: h ^= data[2] << 16;
							 | 
						||
| 
								 | 
							
									case 2: h ^= data[1] << 8;
							 | 
						||
| 
								 | 
							
									case 1: h ^= data[0];
							 | 
						||
| 
								 | 
							
									h *= m;
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    } else
							 | 
						||
| 
								 | 
							
								    { switch(len)
							 | 
						||
| 
								 | 
							
								      { case 3: d |= data[2] << 16;
							 | 
						||
| 
								 | 
							
									case 2: d |= data[1] << 8;
							 | 
						||
| 
								 | 
							
									case 1: d |= data[0];
							 | 
						||
| 
								 | 
							
									case 0: h ^= (t >> sr) | (d << sl);
							 | 
						||
| 
								 | 
							
									h *= m;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    h ^= h >> 13;
							 | 
						||
| 
								 | 
							
								    h *= m;
							 | 
						||
| 
								 | 
							
								    h ^= h >> 15;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return h;
							 | 
						||
| 
								 | 
							
								  } else
							 | 
						||
| 
								 | 
							
								  { while( len >= 4 )
							 | 
						||
| 
								 | 
							
								    { unsigned int k = *(unsigned int *)data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      MIX(h,k,m);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      data += 4;
							 | 
						||
| 
								 | 
							
								      len -= 4;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch(len)
							 | 
						||
| 
								 | 
							
								    { case 3: h ^= data[2] << 16;
							 | 
						||
| 
								 | 
							
								      case 2: h ^= data[1] << 8;
							 | 
						||
| 
								 | 
							
								      case 1: h ^= data[0];
							 | 
						||
| 
								 | 
							
								      h *= m;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    h ^= h >> 13;
							 | 
						||
| 
								 | 
							
								    h *= m;
							 | 
						||
| 
								 | 
							
								    h ^= h >> 15;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    return h;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /*WORDS_BIGENDIAN*/
							 |