github.com/whatap/golib@v0.0.22/util/hll/MurmurHash.go (about) 1 /* 2 * This file from 3 * https://github.com/addthis/stream-lib/blob/master/src/main/java/com/clearspring/analytics/hash/MurmurHash.java 4 * 5 * This class modified by Scouter-Project * - original package : com.clearspring.analytics.hash 6 * 7 */ 8 /** 9 * Licensed to the Apache Software Foundation (ASF) under one or more 10 * contributor license agreements. See the NOTICE file distributed with this 11 * work for additional information regarding copyright ownership. The ASF 12 * licenses this file to you under the Apache License, Version 2.0 (the 13 * "License"); you may not use this file except in compliance with the License. 14 * You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, software 19 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 21 * License for the specific language governing permissions and limitations under 22 * the License. 23 * 24 */ 25 /** 26 * This is a very fast, non-cryptographic hash suitable for general hash-based 27 * lookup. See http://murmurhash.googlepages.com/ for more details. 28 * <p/> 29 * <p> 30 * The C version of MurmurHash 2.0 found at that site was ported to Java by 31 * Andrzej Bialecki (ab at getopt org). 32 * </p> 33 */ 34 package hll 35 36 import () 37 38 //func MurmurHash(Object o) int { 39 // if (o == null) { 40 // return 0; 41 // } 42 // if (o instanceof Long) { 43 // return hashLong((Long) o); 44 // } 45 // if (o instanceof Integer) { 46 // return hashLong((Integer) o); 47 // } 48 // if (o instanceof Double) { 49 // return hashLong(Double.doubleToRawLongBits((Double) o)); 50 // } 51 // if (o instanceof Float) { 52 // return hashLong(Float.floatToRawIntBits((Float) o)); 53 // } 54 // if (o instanceof String) { 55 // return hash(((String) o).getBytes()); 56 // } 57 // if (o instanceof byte[]) { 58 // return hash((byte[]) o); 59 // } 60 // 61 // return hash(o.toString()); 62 // } 63 func MurmurHash(o uint32) uint32 { 64 return MurmurHashLong(uint64(o)) 65 } 66 67 func MurmurHashByte(data []byte) uint32 { 68 return murmurHash(data, int32(len(data)), 0xe17a1465) 69 } 70 func MurmurHashByteSeed(data []byte, seed uint32) uint32 { 71 return murmurHash(data, int32(len(data)), seed) 72 } 73 func murmurHash(data []byte, length int32, seed uint32) uint32 { 74 m := uint32(0x5bd1e995) 75 r := uint32(24) 76 h := seed ^ uint32(length) 77 len_4 := uint32(length) >> 2 78 79 for i := 0; i < int(len_4); i++ { 80 i_4 := i << 2 81 k := uint32(data[i_4+3]) 82 k = k << 8 83 k = k | uint32(data[i_4+2]) & 0xff 84 k = k << 8 85 k = k | uint32(data[i_4+1]) & 0xff 86 k = k << 8 87 k = k | uint32(data[i_4+0]) & 0xff 88 k *= m 89 //k ^= k >>> r 90 k ^= k >> r 91 k *= m 92 h *= m 93 h ^= k 94 } 95 // avoid calculating modulo 96 len_m := len_4 << 2 97 left := uint32(length) - len_m 98 if left != 0 { 99 if left >= 3 { 100 h ^= uint32(data[length-3]) << 16 101 } 102 if left >= 2 { 103 h ^= uint32(data[length-2]) << 8 104 } 105 if left >= 1 { 106 h ^= uint32(data[length-1]) 107 } 108 h *= m 109 } 110 h ^= h >> 13 111 h *= m 112 h ^= h >> 15 113 114 return h 115 } 116 117 func MurmurHashLong(data uint64) uint32 { 118 m := uint32(0x5bd1e995) 119 r := uint32(24) 120 h := uint32(0) 121 k := uint32(data * uint64(m)) 122 //k ^= k >>> r 123 k ^= k >> r 124 h ^= k * m 125 k = uint32((data >> 32) * uint64(m)) 126 //k ^= k >>> r; 127 k ^= k >> r 128 h *= m 129 h ^= k * m 130 //h ^= h >>> 13; 131 h ^= h >> 13 132 h *= m 133 //h ^= h >>> 15; 134 h ^= h >> 15 135 136 return h 137 } 138 139 //func MurmurHash64(Object o) int64 { 140 // if (o == null) { 141 // return 0l; 142 // } else if (o instanceof String) { 143 // final byte[] bytes = ((String) o).getBytes(); 144 // return hash64(bytes, bytes.length); 145 // } else if (o instanceof byte[]) { 146 // final byte[] bytes = (byte[]) o; 147 // return hash64(bytes, bytes.length); 148 // } 149 // return hash64(o.toString()); 150 // } 151 // 64 bit implementation copied from here: https://github.com/tnm/murmurhash-java 152 /** 153 * Generates 64 bit hash from byte array with default seed value. 154 * 155 * @param data byte array to hash 156 * @param length length of the array to hash 157 * @return 64 bit hash of the given string 158 */ 159 func MurmurHashLongByte(data []byte, length int32) uint64 { 160 return murmurHashLong(data, length, 0xe17a1465) 161 } 162 163 /** 164 * Generates 64 bit hash from byte array of the given length and seed. 165 * 166 * @param data byte array to hash 167 * @param length length of the array to hash 168 * @param seed initial seed value 169 * @return 64 bit hash of the given array 170 */ 171 func murmurHashLong(data []byte, length int32, seed uint32) uint64 { 172 //m := 0xc6a4a7935bd1e995L 173 m := uint64(0xc6a4a7935bd1e995) 174 r := uint64(47) 175 //h := (seed & 0xffffffffl) ^ (length * m) 176 h := uint64(seed & 0xffffffff) ^ (uint64(length) * m) 177 length8 := length / 8 178 for i := 0; i < int(length8); i++ { 179 i8 := i * 8 180 k := (uint64(data[i8+0]) & 0xff) + ((uint64(data[i8+1]) & 0xff) << 8) + 181 ((uint64(data[i8+2]) & 0xff) << 16) + ((uint64(data[i8+3]) & 0xff) << 24) + 182 ((uint64(data[i8+4]) & 0xff) << 32) + ((uint64(data[i8+5]) & 0xff) << 40) + 183 ((uint64(data[i8+6]) & 0xff) << 48) + ((uint64(data[i8+7]) & 0xff) << 56) 184 k *= m 185 //k ^= k >>> r 186 k ^= k >> r 187 k *= m 188 h ^= k 189 h *= m 190 } 191 switch length % 8 { 192 case 7: 193 //h ^= (long) (data[(length & ~7) + 6] & 0xff) << 48; 194 h ^= (uint64(data[(length & ^7)+6])&0xff) << 48 195 fallthrough 196 case 6: 197 h ^= uint64(data[(length & ^7)+5]&0xff) << 40 198 fallthrough 199 case 5: 200 h ^= uint64(data[(length & ^7)+4]&0xff) << 32 201 fallthrough 202 case 4: 203 h ^= uint64(data[(length & ^7)+3]&0xff) << 24 204 fallthrough 205 case 3: 206 h ^= uint64(data[(length & ^7)+2]&0xff) << 16 207 fallthrough 208 case 2: 209 h ^= uint64(data[(length & ^7)+1]&0xff) << 8 210 fallthrough 211 case 1: 212 h ^= uint64(data[length & ^7] & 0xff) 213 h *= m 214 } 215 //h ^= h >>> r; 216 h ^= h >> r 217 h *= m 218 //h ^= h >>> r; 219 h ^= h >> r 220 return h 221 }