github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zarray/hash.go (about)

     1  //go:build go1.18
     2  // +build go1.18
     3  
     4  package zarray
     5  
     6  import (
     7  	"encoding/binary"
     8  	"math/bits"
     9  	"reflect"
    10  	"unsafe"
    11  )
    12  
    13  const (
    14  	// hash input allowed sizes
    15  	byteSize = 1 << iota
    16  	wordSize
    17  	dwordSize
    18  	qwordSize
    19  	owordSize
    20  )
    21  
    22  const (
    23  	prime1 uint64 = 11400714785074694791
    24  	prime2 uint64 = 14029467366897019727
    25  	prime3 uint64 = 1609587929392839161
    26  	prime4 uint64 = 9650029242287828579
    27  	prime5 uint64 = 2870177450012600261
    28  )
    29  
    30  var prime1v = prime1
    31  
    32  func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
    33  func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
    34  
    35  func round(acc, input uint64) uint64 {
    36  	acc += input * prime2
    37  	acc = rol31(acc)
    38  	acc *= prime1
    39  	return acc
    40  }
    41  
    42  func mergeRound(acc, val uint64) uint64 {
    43  	val = round(0, val)
    44  	acc ^= val
    45  	acc = acc*prime1 + prime4
    46  	return acc
    47  }
    48  
    49  func rol1(x uint64) uint64  { return bits.RotateLeft64(x, 1) }
    50  func rol7(x uint64) uint64  { return bits.RotateLeft64(x, 7) }
    51  func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) }
    52  func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) }
    53  func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) }
    54  func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) }
    55  func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) }
    56  func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) }
    57  
    58  var (
    59  	byteHasher = func(key uint8) uintptr {
    60  		h := prime5 + 1
    61  		h ^= uint64(key) * prime5
    62  		h = bits.RotateLeft64(h, 11) * prime1
    63  		h ^= h >> 33
    64  		h *= prime2
    65  		h ^= h >> 29
    66  		h *= prime3
    67  		h ^= h >> 32
    68  		return uintptr(h)
    69  	}
    70  
    71  	wordHasher = func(key uint16) uintptr {
    72  		h := prime5 + 2
    73  		h ^= (uint64(key) & 0xff) * prime5
    74  		h = bits.RotateLeft64(h, 11) * prime1
    75  		h ^= ((uint64(key) >> 8) & 0xff) * prime5
    76  		h = bits.RotateLeft64(h, 11) * prime1
    77  		h ^= h >> 33
    78  		h *= prime2
    79  		h ^= h >> 29
    80  		h *= prime3
    81  		h ^= h >> 32
    82  		return uintptr(h)
    83  	}
    84  
    85  	dwordHasher = func(key uint32) uintptr {
    86  		h := prime5 + 4
    87  		h ^= uint64(key) * prime1
    88  		h = bits.RotateLeft64(h, 23)*prime2 + prime3
    89  		h ^= h >> 33
    90  		h *= prime2
    91  		h ^= h >> 29
    92  		h *= prime3
    93  		h ^= h >> 32
    94  		return uintptr(h)
    95  	}
    96  
    97  	float32Hasher = func(key float32) uintptr {
    98  		h := prime5 + 4
    99  		h ^= uint64(*(*uint32)(unsafe.Pointer(&key))) * prime1
   100  		h = bits.RotateLeft64(h, 23)*prime2 + prime3
   101  		h ^= h >> 33
   102  		h *= prime2
   103  		h ^= h >> 29
   104  		h *= prime3
   105  		h ^= h >> 32
   106  		return uintptr(h)
   107  	}
   108  
   109  	qwordHasher = func(key uint64) uintptr {
   110  		k1 := key * prime2
   111  		k1 = bits.RotateLeft64(k1, 31)
   112  		k1 *= prime1
   113  		h := (prime5 + 8) ^ k1
   114  		h = bits.RotateLeft64(h, 27)*prime1 + prime4
   115  		h ^= h >> 33
   116  		h *= prime2
   117  		h ^= h >> 29
   118  		h *= prime3
   119  		h ^= h >> 32
   120  		return uintptr(h)
   121  	}
   122  
   123  	float64Hasher = func(key float64) uintptr {
   124  		k1 := *(*uint64)(unsafe.Pointer(&key)) * prime2
   125  		k1 = bits.RotateLeft64(k1, 31)
   126  		k1 *= prime1
   127  		h := (prime5 + 8) ^ k1
   128  		h = bits.RotateLeft64(h, 27)*prime1 + prime4
   129  		h ^= h >> 33
   130  		h *= prime2
   131  		h ^= h >> 29
   132  		h *= prime3
   133  		h ^= h >> 32
   134  		return uintptr(h)
   135  	}
   136  
   137  	complex64Hasher = func(key complex64) uintptr {
   138  		k1 := *(*uint64)(unsafe.Pointer(&key)) * prime2
   139  		k1 = bits.RotateLeft64(k1, 31)
   140  		k1 *= prime1
   141  		h := (prime5 + 8) ^ k1
   142  		h = bits.RotateLeft64(h, 27)*prime1 + prime4
   143  		h ^= h >> 33
   144  		h *= prime2
   145  		h ^= h >> 29
   146  		h *= prime3
   147  		h ^= h >> 32
   148  		return uintptr(h)
   149  	}
   150  )
   151  
   152  func (m *Maper[K, V]) setDefaultHasher() {
   153  	// default hash functions
   154  	switch reflect.TypeOf(*new(K)).Kind() {
   155  	case reflect.String:
   156  		m.hasher = func(key K) uintptr {
   157  			sh := (*reflect.StringHeader)(unsafe.Pointer(&key))
   158  			b := unsafe.Slice((*byte)(unsafe.Pointer(sh.Data)), sh.Len)
   159  			n := sh.Len
   160  			var h uint64
   161  
   162  			if n >= 32 {
   163  				v1 := prime1v + prime2
   164  				v2 := prime2
   165  				v3 := uint64(0)
   166  				v4 := -prime1v
   167  				for len(b) >= 32 {
   168  					v1 = round(v1, u64(b[0:8:len(b)]))
   169  					v2 = round(v2, u64(b[8:16:len(b)]))
   170  					v3 = round(v3, u64(b[16:24:len(b)]))
   171  					v4 = round(v4, u64(b[24:32:len(b)]))
   172  					b = b[32:len(b):len(b)]
   173  				}
   174  				h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
   175  				h = mergeRound(h, v1)
   176  				h = mergeRound(h, v2)
   177  				h = mergeRound(h, v3)
   178  				h = mergeRound(h, v4)
   179  			} else {
   180  				h = prime5
   181  			}
   182  
   183  			h += uint64(n)
   184  
   185  			i, end := 0, len(b)
   186  			for ; i+8 <= end; i += 8 {
   187  				k1 := round(0, u64(b[i:i+8:len(b)]))
   188  				h ^= k1
   189  				h = rol27(h)*prime1 + prime4
   190  			}
   191  			if i+4 <= end {
   192  				h ^= uint64(u32(b[i:i+4:len(b)])) * prime1
   193  				h = rol23(h)*prime2 + prime3
   194  				i += 4
   195  			}
   196  			for ; i < end; i++ {
   197  				h ^= uint64(b[i]) * prime5
   198  				h = rol11(h) * prime1
   199  			}
   200  
   201  			h ^= h >> 33
   202  			h *= prime2
   203  			h ^= h >> 29
   204  			h *= prime3
   205  			h ^= h >> 32
   206  
   207  			return uintptr(h)
   208  		}
   209  	case reflect.Int, reflect.Uint, reflect.Uintptr, reflect.UnsafePointer:
   210  		switch intSizeBytes {
   211  		case 2:
   212  			// word hasher
   213  			m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&wordHasher))
   214  		case 4:
   215  			// dword hasher
   216  			m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&dwordHasher))
   217  		case 8:
   218  			// qword hasher
   219  			m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&qwordHasher))
   220  		}
   221  	case reflect.Int8, reflect.Uint8:
   222  		// byte hasher
   223  		m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&byteHasher))
   224  	case reflect.Int16, reflect.Uint16:
   225  		// word hasher
   226  		m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&wordHasher))
   227  	case reflect.Int32, reflect.Uint32:
   228  		// dword hasher
   229  		m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&dwordHasher))
   230  	case reflect.Float32:
   231  		// custom float32 dword hasher
   232  		m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&float32Hasher))
   233  	case reflect.Int64, reflect.Uint64:
   234  		// qword hasher
   235  		m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&qwordHasher))
   236  	case reflect.Float64:
   237  		// custom float64 qword hasher
   238  		m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&float64Hasher))
   239  	case reflect.Complex64:
   240  		// custom complex64 qword hasher
   241  		m.hasher = *(*func(K) uintptr)(unsafe.Pointer(&complex64Hasher))
   242  	case reflect.Complex128:
   243  		// oword hasher, key size -> 16 bytes
   244  		m.hasher = func(key K) uintptr {
   245  			b := *(*[owordSize]byte)(unsafe.Pointer(&key))
   246  			h := prime5 + 16
   247  
   248  			val := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
   249  				uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
   250  
   251  			k1 := val * prime2
   252  			k1 = bits.RotateLeft64(k1, 31)
   253  			k1 *= prime1
   254  
   255  			h ^= k1
   256  			h = bits.RotateLeft64(h, 27)*prime1 + prime4
   257  
   258  			val = uint64(b[8]) | uint64(b[9])<<8 | uint64(b[10])<<16 | uint64(b[11])<<24 |
   259  				uint64(b[12])<<32 | uint64(b[13])<<40 | uint64(b[14])<<48 | uint64(b[15])<<56
   260  
   261  			k1 = val * prime2
   262  			k1 = bits.RotateLeft64(k1, 31)
   263  			k1 *= prime1
   264  
   265  			h ^= k1
   266  			h = bits.RotateLeft64(h, 27)*prime1 + prime4
   267  
   268  			h ^= h >> 33
   269  			h *= prime2
   270  			h ^= h >> 29
   271  			h *= prime3
   272  			h ^= h >> 32
   273  
   274  			return uintptr(h)
   275  		}
   276  	}
   277  }