github.com/spaolacci/murmur3@v1.1.0/murmur32.go (about)

     1  package murmur3
     2  
     3  // http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/hash/Murmur3_32HashFunction.java
     4  
     5  import (
     6  	"hash"
     7  	"unsafe"
     8  )
     9  
    10  // Make sure interfaces are correctly implemented.
    11  var (
    12  	_ hash.Hash   = new(digest32)
    13  	_ hash.Hash32 = new(digest32)
    14  	_ bmixer      = new(digest32)
    15  )
    16  
    17  const (
    18  	c1_32 uint32 = 0xcc9e2d51
    19  	c2_32 uint32 = 0x1b873593
    20  )
    21  
    22  // digest32 represents a partial evaluation of a 32 bites hash.
    23  type digest32 struct {
    24  	digest
    25  	h1 uint32 // Unfinalized running hash.
    26  }
    27  
    28  // New32 returns new 32-bit hasher
    29  func New32() hash.Hash32 { return New32WithSeed(0) }
    30  
    31  // New32WithSeed returns new 32-bit hasher set with explicit seed value
    32  func New32WithSeed(seed uint32) hash.Hash32 {
    33  	d := new(digest32)
    34  	d.seed = seed
    35  	d.bmixer = d
    36  	d.Reset()
    37  	return d
    38  }
    39  
    40  func (d *digest32) Size() int { return 4 }
    41  
    42  func (d *digest32) reset() { d.h1 = d.seed }
    43  
    44  func (d *digest32) Sum(b []byte) []byte {
    45  	h := d.Sum32()
    46  	return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h))
    47  }
    48  
    49  // Digest as many blocks as possible.
    50  func (d *digest32) bmix(p []byte) (tail []byte) {
    51  	h1 := d.h1
    52  
    53  	nblocks := len(p) / 4
    54  	for i := 0; i < nblocks; i++ {
    55  		k1 := *(*uint32)(unsafe.Pointer(&p[i*4]))
    56  
    57  		k1 *= c1_32
    58  		k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
    59  		k1 *= c2_32
    60  
    61  		h1 ^= k1
    62  		h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13)
    63  		h1 = h1*4 + h1 + 0xe6546b64
    64  	}
    65  	d.h1 = h1
    66  	return p[nblocks*d.Size():]
    67  }
    68  
    69  func (d *digest32) Sum32() (h1 uint32) {
    70  
    71  	h1 = d.h1
    72  
    73  	var k1 uint32
    74  	switch len(d.tail) & 3 {
    75  	case 3:
    76  		k1 ^= uint32(d.tail[2]) << 16
    77  		fallthrough
    78  	case 2:
    79  		k1 ^= uint32(d.tail[1]) << 8
    80  		fallthrough
    81  	case 1:
    82  		k1 ^= uint32(d.tail[0])
    83  		k1 *= c1_32
    84  		k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
    85  		k1 *= c2_32
    86  		h1 ^= k1
    87  	}
    88  
    89  	h1 ^= uint32(d.clen)
    90  
    91  	h1 ^= h1 >> 16
    92  	h1 *= 0x85ebca6b
    93  	h1 ^= h1 >> 13
    94  	h1 *= 0xc2b2ae35
    95  	h1 ^= h1 >> 16
    96  
    97  	return h1
    98  }
    99  
   100  /*
   101  func rotl32(x uint32, r byte) uint32 {
   102  	return (x << r) | (x >> (32 - r))
   103  }
   104  */
   105  
   106  // Sum32 returns the MurmurHash3 sum of data. It is equivalent to the
   107  // following sequence (without the extra burden and the extra allocation):
   108  //     hasher := New32()
   109  //     hasher.Write(data)
   110  //     return hasher.Sum32()
   111  func Sum32(data []byte) uint32 { return Sum32WithSeed(data, 0) }
   112  
   113  // Sum32WithSeed returns the MurmurHash3 sum of data. It is equivalent to the
   114  // following sequence (without the extra burden and the extra allocation):
   115  //     hasher := New32WithSeed(seed)
   116  //     hasher.Write(data)
   117  //     return hasher.Sum32()
   118  func Sum32WithSeed(data []byte, seed uint32) uint32 {
   119  
   120  	h1 := seed
   121  
   122  	nblocks := len(data) / 4
   123  	var p uintptr
   124  	if len(data) > 0 {
   125  		p = uintptr(unsafe.Pointer(&data[0]))
   126  	}
   127  	p1 := p + uintptr(4*nblocks)
   128  	for ; p < p1; p += 4 {
   129  		k1 := *(*uint32)(unsafe.Pointer(p))
   130  
   131  		k1 *= c1_32
   132  		k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
   133  		k1 *= c2_32
   134  
   135  		h1 ^= k1
   136  		h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13)
   137  		h1 = h1*4 + h1 + 0xe6546b64
   138  	}
   139  
   140  	tail := data[nblocks*4:]
   141  
   142  	var k1 uint32
   143  	switch len(tail) & 3 {
   144  	case 3:
   145  		k1 ^= uint32(tail[2]) << 16
   146  		fallthrough
   147  	case 2:
   148  		k1 ^= uint32(tail[1]) << 8
   149  		fallthrough
   150  	case 1:
   151  		k1 ^= uint32(tail[0])
   152  		k1 *= c1_32
   153  		k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
   154  		k1 *= c2_32
   155  		h1 ^= k1
   156  	}
   157  
   158  	h1 ^= uint32(len(data))
   159  
   160  	h1 ^= h1 >> 16
   161  	h1 *= 0x85ebca6b
   162  	h1 ^= h1 >> 13
   163  	h1 *= 0xc2b2ae35
   164  	h1 ^= h1 >> 16
   165  
   166  	return h1
   167  }