pax_global_header00006660000000000000000000000064131457624250014523gustar00rootroot0000000000000052 comment=9f5d223c60793748f04a9d5b4b4eacddfc1f755d murmur3-1.1/000077500000000000000000000000001314576242500127765ustar00rootroot00000000000000murmur3-1.1/.gitignore000066400000000000000000000003741314576242500147720ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe murmur3-1.1/.travis.yml000066400000000000000000000000721314576242500151060ustar00rootroot00000000000000language: go go: - 1.x - master script: go test murmur3-1.1/LICENSE000066400000000000000000000027301314576242500140050ustar00rootroot00000000000000Copyright 2013, Sébastien Paolacci. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the library nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. murmur3-1.1/README.md000066400000000000000000000123111314576242500142530ustar00rootroot00000000000000murmur3 ======= [![Build Status](https://travis-ci.org/spaolacci/murmur3.svg?branch=master)](https://travis-ci.org/spaolacci/murmur3) Native Go implementation of Austin Appleby's third MurmurHash revision (aka MurmurHash3). Reference algorithm has been slightly hacked as to support the streaming mode required by Go's standard [Hash interface](http://golang.org/pkg/hash/#Hash). Benchmarks ---------- Go tip as of 2014-06-12 (i.e almost go1.3), core i7 @ 3.4 Ghz. All runs include hasher instantiation and sequence finalization.

Benchmark32_1        500000000     7.69 ns/op      130.00 MB/s
Benchmark32_2        200000000     8.83 ns/op      226.42 MB/s
Benchmark32_4        500000000     7.99 ns/op      500.39 MB/s
Benchmark32_8        200000000     9.47 ns/op      844.69 MB/s
Benchmark32_16       100000000     12.1 ns/op     1321.61 MB/s
Benchmark32_32       100000000     18.3 ns/op     1743.93 MB/s
Benchmark32_64        50000000     30.9 ns/op     2071.64 MB/s
Benchmark32_128       50000000     57.6 ns/op     2222.96 MB/s
Benchmark32_256       20000000      116 ns/op     2188.60 MB/s
Benchmark32_512       10000000      226 ns/op     2260.59 MB/s
Benchmark32_1024       5000000      452 ns/op     2263.73 MB/s
Benchmark32_2048       2000000      891 ns/op     2296.02 MB/s
Benchmark32_4096       1000000     1787 ns/op     2290.92 MB/s
Benchmark32_8192        500000     3593 ns/op     2279.68 MB/s
Benchmark128_1       100000000     26.1 ns/op       38.33 MB/s
Benchmark128_2       100000000     29.0 ns/op       69.07 MB/s
Benchmark128_4        50000000     29.8 ns/op      134.17 MB/s
Benchmark128_8        50000000     31.6 ns/op      252.86 MB/s
Benchmark128_16      100000000     26.5 ns/op      603.42 MB/s
Benchmark128_32      100000000     28.6 ns/op     1117.15 MB/s
Benchmark128_64       50000000     35.5 ns/op     1800.97 MB/s
Benchmark128_128      50000000     50.9 ns/op     2515.50 MB/s
Benchmark128_256      20000000     76.9 ns/op     3330.11 MB/s
Benchmark128_512      20000000      135 ns/op     3769.09 MB/s
Benchmark128_1024     10000000      250 ns/op     4094.38 MB/s
Benchmark128_2048      5000000      477 ns/op     4290.75 MB/s
Benchmark128_4096      2000000      940 ns/op     4353.29 MB/s
Benchmark128_8192      1000000     1838 ns/op     4455.47 MB/s


benchmark              Go1.0 MB/s    Go1.1 MB/s  speedup    Go1.2 MB/s  speedup    Go1.3 MB/s  speedup
Benchmark32_1               98.90        118.59    1.20x        114.79    0.97x        130.00    1.13x
Benchmark32_2              168.04        213.31    1.27x        210.65    0.99x        226.42    1.07x
Benchmark32_4              414.01        494.19    1.19x        490.29    0.99x        500.39    1.02x
Benchmark32_8              662.19        836.09    1.26x        836.46    1.00x        844.69    1.01x
Benchmark32_16             917.46       1304.62    1.42x       1297.63    0.99x       1321.61    1.02x
Benchmark32_32            1141.93       1737.54    1.52x       1728.24    0.99x       1743.93    1.01x
Benchmark32_64            1289.47       2039.51    1.58x       2038.20    1.00x       2071.64    1.02x
Benchmark32_128           1299.23       2097.63    1.61x       2177.13    1.04x       2222.96    1.02x
Benchmark32_256           1369.90       2202.34    1.61x       2213.15    1.00x       2188.60    0.99x
Benchmark32_512           1399.56       2255.72    1.61x       2264.49    1.00x       2260.59    1.00x
Benchmark32_1024          1410.90       2285.82    1.62x       2270.99    0.99x       2263.73    1.00x
Benchmark32_2048          1422.14       2297.62    1.62x       2269.59    0.99x       2296.02    1.01x
Benchmark32_4096          1420.53       2307.81    1.62x       2273.43    0.99x       2290.92    1.01x
Benchmark32_8192          1424.79       2312.87    1.62x       2286.07    0.99x       2279.68    1.00x
Benchmark128_1               8.32         30.15    3.62x         30.84    1.02x         38.33    1.24x
Benchmark128_2              16.38         59.72    3.65x         59.37    0.99x         69.07    1.16x
Benchmark128_4              32.26        112.96    3.50x        114.24    1.01x        134.17    1.17x
Benchmark128_8              62.68        217.88    3.48x        218.18    1.00x        252.86    1.16x
Benchmark128_16            128.47        451.57    3.51x        474.65    1.05x        603.42    1.27x
Benchmark128_32            246.18        910.42    3.70x        871.06    0.96x       1117.15    1.28x
Benchmark128_64            449.05       1477.64    3.29x       1449.24    0.98x       1800.97    1.24x
Benchmark128_128           762.61       2222.42    2.91x       2217.30    1.00x       2515.50    1.13x
Benchmark128_256          1179.92       3005.46    2.55x       2931.55    0.98x       3330.11    1.14x
Benchmark128_512          1616.51       3590.75    2.22x       3592.08    1.00x       3769.09    1.05x
Benchmark128_1024         1964.36       3979.67    2.03x       4034.01    1.01x       4094.38    1.01x
Benchmark128_2048         2225.07       4156.93    1.87x       4244.17    1.02x       4290.75    1.01x
Benchmark128_4096         2360.15       4299.09    1.82x       4392.35    1.02x       4353.29    0.99x
Benchmark128_8192         2411.50       4356.84    1.81x       4480.68    1.03x       4455.47    0.99x

murmur3-1.1/murmur.go000066400000000000000000000030071314576242500146540ustar00rootroot00000000000000// Copyright 2013, Sébastien Paolacci. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. /* Package murmur3 implements Austin Appleby's non-cryptographic MurmurHash3. Reference implementation: http://code.google.com/p/smhasher/wiki/MurmurHash3 History, characteristics and (legacy) perfs: https://sites.google.com/site/murmurhash/ https://sites.google.com/site/murmurhash/statistics */ package murmur3 type bmixer interface { bmix(p []byte) (tail []byte) Size() (n int) reset() } type digest struct { clen int // Digested input cumulative length. tail []byte // 0 to Size()-1 bytes view of `buf'. buf [16]byte // Expected (but not required) to be Size() large. seed uint32 // Seed for initializing the hash. bmixer } func (d *digest) BlockSize() int { return 1 } func (d *digest) Write(p []byte) (n int, err error) { n = len(p) d.clen += n if len(d.tail) > 0 { // Stick back pending bytes. nfree := d.Size() - len(d.tail) // nfree ∈ [1, d.Size()-1]. if nfree < len(p) { // One full block can be formed. block := append(d.tail, p[:nfree]...) p = p[nfree:] _ = d.bmix(block) // No tail. } else { // Tail's buf is large enough to prevent reallocs. p = append(d.tail, p...) } } d.tail = d.bmix(p) // Keep own copy of the 0 to Size()-1 pending bytes. nn := copy(d.buf[:], d.tail) d.tail = d.buf[:nn] return n, nil } func (d *digest) Reset() { d.clen = 0 d.tail = nil d.bmixer.reset() } murmur3-1.1/murmur128.go000066400000000000000000000101661314576242500151130ustar00rootroot00000000000000package murmur3 import ( //"encoding/binary" "hash" "unsafe" ) const ( c1_128 = 0x87c37b91114253d5 c2_128 = 0x4cf5ad432745937f ) // Make sure interfaces are correctly implemented. var ( _ hash.Hash = new(digest128) _ Hash128 = new(digest128) _ bmixer = new(digest128) ) // Hash128 represents a 128-bit hasher // Hack: the standard api doesn't define any Hash128 interface. type Hash128 interface { hash.Hash Sum128() (uint64, uint64) } // digest128 represents a partial evaluation of a 128 bites hash. type digest128 struct { digest h1 uint64 // Unfinalized running hash part 1. h2 uint64 // Unfinalized running hash part 2. } // New128 returns a 128-bit hasher func New128() Hash128 { return New128WithSeed(0) } // New128WithSeed returns a 128-bit hasher set with explicit seed value func New128WithSeed(seed uint32) Hash128 { d := new(digest128) d.seed = seed d.bmixer = d d.Reset() return d } func (d *digest128) Size() int { return 16 } func (d *digest128) reset() { d.h1, d.h2 = uint64(d.seed), uint64(d.seed) } func (d *digest128) Sum(b []byte) []byte { h1, h2 := d.Sum128() return append(b, byte(h1>>56), byte(h1>>48), byte(h1>>40), byte(h1>>32), byte(h1>>24), byte(h1>>16), byte(h1>>8), byte(h1), byte(h2>>56), byte(h2>>48), byte(h2>>40), byte(h2>>32), byte(h2>>24), byte(h2>>16), byte(h2>>8), byte(h2), ) } func (d *digest128) bmix(p []byte) (tail []byte) { h1, h2 := d.h1, d.h2 nblocks := len(p) / 16 for i := 0; i < nblocks; i++ { t := (*[2]uint64)(unsafe.Pointer(&p[i*16])) k1, k2 := t[0], t[1] k1 *= c1_128 k1 = (k1 << 31) | (k1 >> 33) // rotl64(k1, 31) k1 *= c2_128 h1 ^= k1 h1 = (h1 << 27) | (h1 >> 37) // rotl64(h1, 27) h1 += h2 h1 = h1*5 + 0x52dce729 k2 *= c2_128 k2 = (k2 << 33) | (k2 >> 31) // rotl64(k2, 33) k2 *= c1_128 h2 ^= k2 h2 = (h2 << 31) | (h2 >> 33) // rotl64(h2, 31) h2 += h1 h2 = h2*5 + 0x38495ab5 } d.h1, d.h2 = h1, h2 return p[nblocks*d.Size():] } func (d *digest128) Sum128() (h1, h2 uint64) { h1, h2 = d.h1, d.h2 var k1, k2 uint64 switch len(d.tail) & 15 { case 15: k2 ^= uint64(d.tail[14]) << 48 fallthrough case 14: k2 ^= uint64(d.tail[13]) << 40 fallthrough case 13: k2 ^= uint64(d.tail[12]) << 32 fallthrough case 12: k2 ^= uint64(d.tail[11]) << 24 fallthrough case 11: k2 ^= uint64(d.tail[10]) << 16 fallthrough case 10: k2 ^= uint64(d.tail[9]) << 8 fallthrough case 9: k2 ^= uint64(d.tail[8]) << 0 k2 *= c2_128 k2 = (k2 << 33) | (k2 >> 31) // rotl64(k2, 33) k2 *= c1_128 h2 ^= k2 fallthrough case 8: k1 ^= uint64(d.tail[7]) << 56 fallthrough case 7: k1 ^= uint64(d.tail[6]) << 48 fallthrough case 6: k1 ^= uint64(d.tail[5]) << 40 fallthrough case 5: k1 ^= uint64(d.tail[4]) << 32 fallthrough case 4: k1 ^= uint64(d.tail[3]) << 24 fallthrough case 3: k1 ^= uint64(d.tail[2]) << 16 fallthrough case 2: k1 ^= uint64(d.tail[1]) << 8 fallthrough case 1: k1 ^= uint64(d.tail[0]) << 0 k1 *= c1_128 k1 = (k1 << 31) | (k1 >> 33) // rotl64(k1, 31) k1 *= c2_128 h1 ^= k1 } h1 ^= uint64(d.clen) h2 ^= uint64(d.clen) h1 += h2 h2 += h1 h1 = fmix64(h1) h2 = fmix64(h2) h1 += h2 h2 += h1 return h1, h2 } func fmix64(k uint64) uint64 { k ^= k >> 33 k *= 0xff51afd7ed558ccd k ^= k >> 33 k *= 0xc4ceb9fe1a85ec53 k ^= k >> 33 return k } /* func rotl64(x uint64, r byte) uint64 { return (x << r) | (x >> (64 - r)) } */ // Sum128 returns the MurmurHash3 sum of data. It is equivalent to the // following sequence (without the extra burden and the extra allocation): // hasher := New128() // hasher.Write(data) // return hasher.Sum128() func Sum128(data []byte) (h1 uint64, h2 uint64) { return Sum128WithSeed(data, 0) } // Sum128WithSeed returns the MurmurHash3 sum of data. It is equivalent to the // following sequence (without the extra burden and the extra allocation): // hasher := New128WithSeed(seed) // hasher.Write(data) // return hasher.Sum128() func Sum128WithSeed(data []byte, seed uint32) (h1 uint64, h2 uint64) { d := &digest128{h1: uint64(seed), h2: uint64(seed)} d.seed = seed d.tail = d.bmix(data) d.clen = len(data) return d.Sum128() } murmur3-1.1/murmur32.go000066400000000000000000000064431314576242500150300ustar00rootroot00000000000000package murmur3 // http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/hash/Murmur3_32HashFunction.java import ( "hash" "unsafe" ) // Make sure interfaces are correctly implemented. var ( _ hash.Hash = new(digest32) _ hash.Hash32 = new(digest32) _ bmixer = new(digest32) ) const ( c1_32 uint32 = 0xcc9e2d51 c2_32 uint32 = 0x1b873593 ) // digest32 represents a partial evaluation of a 32 bites hash. type digest32 struct { digest h1 uint32 // Unfinalized running hash. } // New32 returns new 32-bit hasher func New32() hash.Hash32 { return New32WithSeed(0) } // New32WithSeed returns new 32-bit hasher set with explicit seed value func New32WithSeed(seed uint32) hash.Hash32 { d := new(digest32) d.seed = seed d.bmixer = d d.Reset() return d } func (d *digest32) Size() int { return 4 } func (d *digest32) reset() { d.h1 = d.seed } func (d *digest32) Sum(b []byte) []byte { h := d.Sum32() return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h)) } // Digest as many blocks as possible. func (d *digest32) bmix(p []byte) (tail []byte) { h1 := d.h1 nblocks := len(p) / 4 for i := 0; i < nblocks; i++ { k1 := *(*uint32)(unsafe.Pointer(&p[i*4])) k1 *= c1_32 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) k1 *= c2_32 h1 ^= k1 h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13) h1 = h1*4 + h1 + 0xe6546b64 } d.h1 = h1 return p[nblocks*d.Size():] } func (d *digest32) Sum32() (h1 uint32) { h1 = d.h1 var k1 uint32 switch len(d.tail) & 3 { case 3: k1 ^= uint32(d.tail[2]) << 16 fallthrough case 2: k1 ^= uint32(d.tail[1]) << 8 fallthrough case 1: k1 ^= uint32(d.tail[0]) k1 *= c1_32 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) k1 *= c2_32 h1 ^= k1 } h1 ^= uint32(d.clen) h1 ^= h1 >> 16 h1 *= 0x85ebca6b h1 ^= h1 >> 13 h1 *= 0xc2b2ae35 h1 ^= h1 >> 16 return h1 } /* func rotl32(x uint32, r byte) uint32 { return (x << r) | (x >> (32 - r)) } */ // Sum32 returns the MurmurHash3 sum of data. It is equivalent to the // following sequence (without the extra burden and the extra allocation): // hasher := New32() // hasher.Write(data) // return hasher.Sum32() func Sum32(data []byte) uint32 { return Sum32WithSeed(data, 0) } // Sum32WithSeed returns the MurmurHash3 sum of data. It is equivalent to the // following sequence (without the extra burden and the extra allocation): // hasher := New32WithSeed(seed) // hasher.Write(data) // return hasher.Sum32() func Sum32WithSeed(data []byte, seed uint32) uint32 { h1 := seed nblocks := len(data) / 4 var p uintptr if len(data) > 0 { p = uintptr(unsafe.Pointer(&data[0])) } p1 := p + uintptr(4*nblocks) for ; p < p1; p += 4 { k1 := *(*uint32)(unsafe.Pointer(p)) k1 *= c1_32 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) k1 *= c2_32 h1 ^= k1 h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13) h1 = h1*4 + h1 + 0xe6546b64 } tail := data[nblocks*4:] var k1 uint32 switch len(tail) & 3 { case 3: k1 ^= uint32(tail[2]) << 16 fallthrough case 2: k1 ^= uint32(tail[1]) << 8 fallthrough case 1: k1 ^= uint32(tail[0]) k1 *= c1_32 k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) k1 *= c2_32 h1 ^= k1 } h1 ^= uint32(len(data)) h1 ^= h1 >> 16 h1 *= 0x85ebca6b h1 ^= h1 >> 13 h1 *= 0xc2b2ae35 h1 ^= h1 >> 16 return h1 } murmur3-1.1/murmur64.go000066400000000000000000000027701314576242500150340ustar00rootroot00000000000000package murmur3 import ( "hash" ) // Make sure interfaces are correctly implemented. var ( _ hash.Hash = new(digest64) _ hash.Hash64 = new(digest64) _ bmixer = new(digest64) ) // digest64 is half a digest128. type digest64 digest128 // New64 returns a 64-bit hasher func New64() hash.Hash64 { return New64WithSeed(0) } // New64WithSeed returns a 64-bit hasher set with explicit seed value func New64WithSeed(seed uint32) hash.Hash64 { d := (*digest64)(New128WithSeed(seed).(*digest128)) return d } func (d *digest64) Sum(b []byte) []byte { h1 := d.Sum64() return append(b, byte(h1>>56), byte(h1>>48), byte(h1>>40), byte(h1>>32), byte(h1>>24), byte(h1>>16), byte(h1>>8), byte(h1)) } func (d *digest64) Sum64() uint64 { h1, _ := (*digest128)(d).Sum128() return h1 } // Sum64 returns the MurmurHash3 sum of data. It is equivalent to the // following sequence (without the extra burden and the extra allocation): // hasher := New64() // hasher.Write(data) // return hasher.Sum64() func Sum64(data []byte) uint64 { return Sum64WithSeed(data, 0) } // Sum64WithSeed returns the MurmurHash3 sum of data. It is equivalent to the // following sequence (without the extra burden and the extra allocation): // hasher := New64WithSeed(seed) // hasher.Write(data) // return hasher.Sum64() func Sum64WithSeed(data []byte, seed uint32) uint64 { d := &digest128{h1: uint64(seed), h2: uint64(seed)} d.seed = seed d.tail = d.bmix(data) d.clen = len(data) h1, _ := d.Sum128() return h1 } murmur3-1.1/murmur_test.go000066400000000000000000000152071314576242500157200ustar00rootroot00000000000000package murmur3 import ( "fmt" "testing" ) var data = []struct { seed uint32 h32 uint32 h64_1 uint64 h64_2 uint64 s string }{ {0x00, 0x00000000, 0x0000000000000000, 0x0000000000000000, ""}, {0x00, 0x248bfa47, 0xcbd8a7b341bd9b02, 0x5b1e906a48ae1d19, "hello"}, {0x00, 0x149bbb7f, 0x342fac623a5ebc8e, 0x4cdcbc079642414d, "hello, world"}, {0x00, 0xe31e8a70, 0xb89e5988b737affc, 0x664fc2950231b2cb, "19 Jan 2038 at 3:14:07 AM"}, {0x00, 0xd5c48bfc, 0xcd99481f9ee902c9, 0x695da1a38987b6e7, "The quick brown fox jumps over the lazy dog."}, {0x01, 0x514e28b7, 0x4610abe56eff5cb5, 0x51622daa78f83583, ""}, {0x01, 0xbb4abcad, 0xa78ddff5adae8d10, 0x128900ef20900135, "hello"}, {0x01, 0x6f5cb2e9, 0x8b95f808840725c6, 0x1597ed5422bd493b, "hello, world"}, {0x01, 0xf50e1f30, 0x2a929de9c8f97b2f, 0x56a41d99af43a2db, "19 Jan 2038 at 3:14:07 AM"}, {0x01, 0x846f6a36, 0xfb3325171f9744da, 0xaaf8b92a5f722952, "The quick brown fox jumps over the lazy dog."}, {0x2a, 0x087fcd5c, 0xf02aa77dfa1b8523, 0xd1016610da11cbb9, ""}, {0x2a, 0xe2dbd2e1, 0xc4b8b3c960af6f08, 0x2334b875b0efbc7a, "hello"}, {0x2a, 0x7ec7c6c2, 0xb91864d797caa956, 0xd5d139a55afe6150, "hello, world"}, {0x2a, 0x58f745f6, 0xfd8f19ebdc8c6b6a, 0xd30fdc310fa08ff9, "19 Jan 2038 at 3:14:07 AM"}, {0x2a, 0xc02d1434, 0x74f33c659cda5af7, 0x4ec7a891caf316f0, "The quick brown fox jumps over the lazy dog."}, } func TestRefStrings(t *testing.T) { for _, elem := range data { h32 := New32WithSeed(elem.seed) h32.Write([]byte(elem.s)) if v := h32.Sum32(); v != elem.h32 { t.Errorf("[Hash32] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h32) } h32.Reset() h32.Write([]byte(elem.s)) target := fmt.Sprintf("%08x", elem.h32) if p := fmt.Sprintf("%x", h32.Sum(nil)); p != target { t.Errorf("[Hash32] key: '%s', seed: '%d': %s (want %s)", elem.s, elem.seed, p, target) } if v := Sum32WithSeed([]byte(elem.s), elem.seed); v != elem.h32 { t.Errorf("[Hash32] key '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h32) } h64 := New64WithSeed(elem.seed) h64.Write([]byte(elem.s)) if v := h64.Sum64(); v != elem.h64_1 { t.Errorf("'[Hash64] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h64_1) } h64.Reset() h64.Write([]byte(elem.s)) target = fmt.Sprintf("%016x", elem.h64_1) if p := fmt.Sprintf("%x", h64.Sum(nil)); p != target { t.Errorf("[Hash64] key: '%s', seed: '%d': %s (want %s)", elem.s, elem.seed, p, target) } if v := Sum64WithSeed([]byte(elem.s), elem.seed); v != elem.h64_1 { t.Errorf("[Hash64] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h64_1) } h128 := New128WithSeed(elem.seed) h128.Write([]byte(elem.s)) if v1, v2 := h128.Sum128(); v1 != elem.h64_1 || v2 != elem.h64_2 { t.Errorf("[Hash128] key: '%s', seed: '%d': 0x%x-0x%x (want 0x%x-0x%x)", elem.s, elem.seed, v1, v2, elem.h64_1, elem.h64_2) } h128.Reset() h128.Write([]byte(elem.s)) target = fmt.Sprintf("%016x%016x", elem.h64_1, elem.h64_2) if p := fmt.Sprintf("%x", h128.Sum(nil)); p != target { t.Errorf("[Hash128] key: '%s', seed: '%d': %s (want %s)", elem.s, elem.seed, p, target) } if v1, v2 := Sum128WithSeed([]byte(elem.s), elem.seed); v1 != elem.h64_1 || v2 != elem.h64_2 { t.Errorf("[Hash128] key: '%s', seed: '%d': 0x%x-0x%x (want 0x%x-0x%x)", elem.s, elem.seed, v1, v2, elem.h64_1, elem.h64_2) } } } func TestIncremental(t *testing.T) { for _, elem := range data { h32 := New32WithSeed(elem.seed) h128 := New128WithSeed(elem.seed) var i, j int for k := len(elem.s); i < k; i = j { j = 2*i + 3 if j > k { j = k } s := elem.s[i:j] print(s + "|") h32.Write([]byte(s)) h128.Write([]byte(s)) } println() if v := h32.Sum32(); v != elem.h32 { t.Errorf("[Hash32] key: '%s', seed: '%d': 0x%x (want 0x%x)", elem.s, elem.seed, v, elem.h32) } if v1, v2 := h128.Sum128(); v1 != elem.h64_1 || v2 != elem.h64_2 { t.Errorf("[Hash128] key: '%s', seed: '%d': 0x%x-0x%x (want 0x%x-0x%x)", elem.s, elem.seed, v1, v2, elem.h64_1, elem.h64_2) } } } //--- func bench32(b *testing.B, length int) { buf := make([]byte, length) b.SetBytes(int64(length)) b.ResetTimer() for i := 0; i < b.N; i++ { Sum32(buf) } } func Benchmark32_1(b *testing.B) { bench32(b, 1) } func Benchmark32_2(b *testing.B) { bench32(b, 2) } func Benchmark32_4(b *testing.B) { bench32(b, 4) } func Benchmark32_8(b *testing.B) { bench32(b, 8) } func Benchmark32_16(b *testing.B) { bench32(b, 16) } func Benchmark32_32(b *testing.B) { bench32(b, 32) } func Benchmark32_64(b *testing.B) { bench32(b, 64) } func Benchmark32_128(b *testing.B) { bench32(b, 128) } func Benchmark32_256(b *testing.B) { bench32(b, 256) } func Benchmark32_512(b *testing.B) { bench32(b, 512) } func Benchmark32_1024(b *testing.B) { bench32(b, 1024) } func Benchmark32_2048(b *testing.B) { bench32(b, 2048) } func Benchmark32_4096(b *testing.B) { bench32(b, 4096) } func Benchmark32_8192(b *testing.B) { bench32(b, 8192) } //--- func benchPartial32(b *testing.B, length int) { buf := make([]byte, length) b.SetBytes(int64(length)) start := (32 / 8) / 2 chunks := 7 k := length / chunks tail := (length - start) % k b.ResetTimer() for i := 0; i < b.N; i++ { hasher := New32() hasher.Write(buf[0:start]) for j := start; j+k <= length; j += k { hasher.Write(buf[j : j+k]) } hasher.Write(buf[length-tail:]) hasher.Sum32() } } func BenchmarkPartial32_8(b *testing.B) { benchPartial32(b, 8) } func BenchmarkPartial32_16(b *testing.B) { benchPartial32(b, 16) } func BenchmarkPartial32_32(b *testing.B) { benchPartial32(b, 32) } func BenchmarkPartial32_64(b *testing.B) { benchPartial32(b, 64) } func BenchmarkPartial32_128(b *testing.B) { benchPartial32(b, 128) } //--- func bench128(b *testing.B, length int) { buf := make([]byte, length) b.SetBytes(int64(length)) b.ResetTimer() for i := 0; i < b.N; i++ { Sum128(buf) } } func Benchmark128_1(b *testing.B) { bench128(b, 1) } func Benchmark128_2(b *testing.B) { bench128(b, 2) } func Benchmark128_4(b *testing.B) { bench128(b, 4) } func Benchmark128_8(b *testing.B) { bench128(b, 8) } func Benchmark128_16(b *testing.B) { bench128(b, 16) } func Benchmark128_32(b *testing.B) { bench128(b, 32) } func Benchmark128_64(b *testing.B) { bench128(b, 64) } func Benchmark128_128(b *testing.B) { bench128(b, 128) } func Benchmark128_256(b *testing.B) { bench128(b, 256) } func Benchmark128_512(b *testing.B) { bench128(b, 512) } func Benchmark128_1024(b *testing.B) { bench128(b, 1024) } func Benchmark128_2048(b *testing.B) { bench128(b, 2048) } func Benchmark128_4096(b *testing.B) { bench128(b, 4096) } func Benchmark128_8192(b *testing.B) { bench128(b, 8192) } //---