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*/
 |