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  }