vitess.io/vitess@v0.16.2/go/mysql/collations/hash.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Copyright 2014 The Go Authors. All rights reserved.
    18  // Use of this source code is governed by a BSD-style
    19  // license that can be found in the LICENSE file.
    20  // all the code in this file has been adapted from the internal hash implementation in the Go runtime:
    21  // https://golang.org/src/runtime/hash64.go
    22  
    23  package collations
    24  
    25  import (
    26  	"math/bits"
    27  	"unsafe"
    28  )
    29  
    30  func memhash(src []byte, seed uintptr) uintptr {
    31  	srclen := len(src)
    32  	if srclen == 0 {
    33  		return seed ^ m1
    34  	}
    35  	return memhashraw(unsafe.Pointer(&src[0]), seed, uintptr(srclen))
    36  }
    37  
    38  func memhashraw(p unsafe.Pointer, seed, s uintptr) uintptr {
    39  	var a, b uintptr
    40  	seed ^= m1
    41  	switch {
    42  	case s == 0:
    43  		return seed
    44  	case s < 4:
    45  		a = uintptr(*(*byte)(p))
    46  		a |= uintptr(*(*byte)(unsafe.Add(p, s>>1))) << 8
    47  		a |= uintptr(*(*byte)(unsafe.Add(p, s-1))) << 16
    48  	case s == 4:
    49  		a = r4(p)
    50  		b = a
    51  	case s < 8:
    52  		a = r4(p)
    53  		b = r4(unsafe.Add(p, s-4))
    54  	case s == 8:
    55  		a = r8(p)
    56  		b = a
    57  	case s <= 16:
    58  		a = r8(p)
    59  		b = r8(unsafe.Add(p, s-8))
    60  	default:
    61  		l := s
    62  		if l > 48 {
    63  			seed1 := seed
    64  			seed2 := seed
    65  			for ; l > 48; l -= 48 {
    66  				seed = mix(r8(p)^m2, r8(unsafe.Add(p, 8))^seed)
    67  				seed1 = mix(r8(unsafe.Add(p, 16))^m3, r8(unsafe.Add(p, 24))^seed1)
    68  				seed2 = mix(r8(unsafe.Add(p, 32))^m4, r8(unsafe.Add(p, 40))^seed2)
    69  				p = unsafe.Add(p, 48)
    70  			}
    71  			seed ^= seed1 ^ seed2
    72  		}
    73  		for ; l > 16; l -= 16 {
    74  			seed = mix(r8(p)^m2, r8(unsafe.Add(p, 8))^seed)
    75  			p = unsafe.Add(p, 16)
    76  		}
    77  		a = r8(unsafe.Add(p, l-16))
    78  		b = r8(unsafe.Add(p, l-8))
    79  	}
    80  
    81  	return mix(m5^s, mix(a^m2, b^seed))
    82  }
    83  
    84  func memhash128(p unsafe.Pointer, seed uintptr) uintptr {
    85  	a := r8(p)
    86  	b := r8(unsafe.Add(p, 8))
    87  	return mix(m5^16, mix(a^m2, b^seed^m1))
    88  }
    89  
    90  func memhash8(p uint8, seed uintptr) uintptr {
    91  	a := uintptr(p)
    92  	return mix(m5^1, mix(a^m2, a^seed^m1))
    93  }
    94  
    95  func memhash16(p uint16, seed uintptr) uintptr {
    96  	a := uintptr(p)
    97  	return mix(m5^2, mix(a^m2, a^seed^m1))
    98  }
    99  
   100  func memhash32(p uint32, seed uintptr) uintptr {
   101  	a := uintptr(p)
   102  	return mix(m5^4, mix(a^m2, a^seed^m1))
   103  }
   104  
   105  func mix(a, b uintptr) uintptr {
   106  	hi, lo := bits.Mul64(uint64(a), uint64(b))
   107  	return uintptr(hi ^ lo)
   108  }
   109  
   110  func r4(p unsafe.Pointer) uintptr {
   111  	return uintptr(readUnaligned32(p))
   112  }
   113  
   114  func r8(p unsafe.Pointer) uintptr {
   115  	return uintptr(readUnaligned64(p))
   116  }
   117  
   118  func readUnaligned32(p unsafe.Pointer) uint32 {
   119  	q := (*[4]byte)(p)
   120  	return uint32(q[0]) | uint32(q[1])<<8 | uint32(q[2])<<16 | uint32(q[3])<<24
   121  }
   122  
   123  func readUnaligned64(p unsafe.Pointer) uint64 {
   124  	q := (*[8]byte)(p)
   125  	return uint64(q[0]) | uint64(q[1])<<8 | uint64(q[2])<<16 | uint64(q[3])<<24 | uint64(q[4])<<32 | uint64(q[5])<<40 | uint64(q[6])<<48 | uint64(q[7])<<56
   126  }