github.com/fluhus/gostuff@v0.4.1-0.20240331134726-be71864f2b5d/rhash/buz32.go (about)

     1  // Implementation of 32-bit buzhash.
     2  
     3  package rhash
     4  
     5  // Buz32 implements a buzhash rolling-hash.
     6  // Implements [hash.Hash32].
     7  type Buz32 struct {
     8  	h uint32 // Current state
     9  	i int    // Number of bytes written
    10  	b []byte // Buffer for subtracting old bytes
    11  }
    12  
    13  // NewBuz32 returns a new rolling hash with a window size of n.
    14  func NewBuz32(n int) *Buz32 {
    15  	return &Buz32{b: make([]byte, n)}
    16  }
    17  
    18  // WriteByte updates the hash with the given byte. Always returns nil.
    19  func (h *Buz32) WriteByte(b byte) error {
    20  	n := len(h.b)
    21  	i := h.i % n
    22  	if h.i >= n { // Need to subtract an old character.
    23  		h.h ^= shift32(buzByteHashes32[h.b[i]], (n-1)%32)
    24  	}
    25  	h.h = shift32(h.h, 1)
    26  	h.h ^= buzByteHashes32[b]
    27  	h.b[i] = b
    28  	h.i++
    29  
    30  	return nil
    31  }
    32  
    33  // Write updates the hash with the given bytes. Always returns len(data), nil.
    34  func (h *Buz32) Write(data []byte) (int, error) {
    35  	for _, b := range data {
    36  		h.WriteByte(b)
    37  	}
    38  	return len(data), nil
    39  }
    40  
    41  // Sum32 returns the current hash.
    42  func (h *Buz32) Sum32() uint32 {
    43  	return h.h
    44  }
    45  
    46  // BlockSize returns the hash's block size, which is one.
    47  func (h *Buz32) BlockSize() int {
    48  	return 1
    49  }
    50  
    51  // Reset resets the hash to its initial state.
    52  func (h *Buz32) Reset() {
    53  	h.h = 0
    54  	h.i = 0
    55  }
    56  
    57  // Size returns the number of bytes Sum will return, which is eight.
    58  func (h *Buz32) Size() int {
    59  	return 8
    60  }
    61  
    62  // Sum appends the current hash to b and returns the resulting slice.
    63  func (h *Buz32) Sum(b []byte) []byte {
    64  	s := h.Sum32()
    65  	n := h.Size()
    66  	for i := 0; i < n; i++ {
    67  		b = append(b, byte(s))
    68  		s >>= 8
    69  	}
    70  	return b
    71  }
    72  
    73  // Returns a cyclic binary left shift by n bits.
    74  func shift32(x uint32, n int) uint32 {
    75  	return x<<n | x>>(32-n)
    76  }
    77  
    78  // Random single-byte hashes.
    79  var buzByteHashes32 = []uint32{
    80  	0xa9215721, 0x56a8a82e, 0xbb391958, 0x53b62323,
    81  	0x778e6e0b, 0x7be66502, 0x8968e901, 0x6185eacb,
    82  	0x745e6971, 0xc02093a0, 0x6d569928, 0x1c1edcdd,
    83  	0x1a3c4c5, 0x130f4, 0x27bdaee2, 0x26be841c,
    84  	0xe49161e0, 0xdcfec2e2, 0x34934ef2, 0x72c11370,
    85  	0xb58b1064, 0x5b68ca2c, 0x68d6c51c, 0xe02537cc,
    86  	0x5840468f, 0x4fc2aeb4, 0xbfb08e36, 0x213071ab,
    87  	0x131602fe, 0xdc839da4, 0x1e48a0d1, 0x877e41b,
    88  	0x27f9189e, 0xb657ae04, 0x34c3daf1, 0xf9342e81,
    89  	0x9824a0b, 0xdb9f349b, 0x98118b96, 0xfe069d09,
    90  	0x1c241430, 0x3c1cd4b6, 0x8ae1b5dd, 0x588e693d,
    91  	0x548bc63a, 0x5ce6fdfb, 0x83e54288, 0x3d45a999,
    92  	0xd8e7c049, 0xa4d5d21d, 0xdc453f61, 0xc51e124a,
    93  	0xfe482ddd, 0x1974340c, 0x384de618, 0xb33e5176,
    94  	0xcb4975bc, 0xec9f16e8, 0xb845cd9a, 0xe68a2257,
    95  	0xae248aff, 0xf391f103, 0xb2d3f7c3, 0x7735f534,
    96  	0x21d6fabd, 0xb227702d, 0x5c9e8bbd, 0xf8ccec5f,
    97  	0xf75aa04b, 0x3c3b2f72, 0x19a72bc0, 0x570dff43,
    98  	0xaa3489be, 0x5c2cdc70, 0x377c8938, 0xc290ded7,
    99  	0x4368318b, 0xd4f71730, 0xd3c11e22, 0x924cb700,
   100  	0x7e84ddb5, 0xda7b2e43, 0x63f834c7, 0xf3512948,
   101  	0x676a381b, 0xde9aaca9, 0xef01a634, 0x1d3edc50,
   102  	0x5789e025, 0x18167241, 0x9b4beab, 0xbf57f3db,
   103  	0xf13b1f6e, 0xa3e7e8e4, 0x9339c30c, 0xd96a1c4d,
   104  	0x479676c7, 0x490b6af9, 0x7cf24154, 0x4e9e7e1c,
   105  	0xd9150b26, 0x920ad2db, 0x9c010130, 0x7dc430e1,
   106  	0x16575ba2, 0x8af855de, 0x4d9a63b7, 0xb64e4234,
   107  	0xf20b8705, 0xaee0c48, 0x2a13dd66, 0xe178fa04,
   108  	0x6447662a, 0xbc752269, 0xba7993e1, 0xead318cb,
   109  	0x955a51f6, 0x8da29e9b, 0xb483a913, 0xd460d0db,
   110  	0x6f450046, 0x4adf1da5, 0xd3cc3c0f, 0xc81a2a65,
   111  	0x4d952b2b, 0xbdc76656, 0xc491e1df, 0x2d828415,
   112  	0x986c8280, 0x97d0ce39, 0x71b0d632, 0xd921f213,
   113  	0x5f00b5dd, 0xccd11167, 0xaedeb970, 0xdf9e1105,
   114  	0xb2632006, 0x4c4d621d, 0xf0f83e37, 0xb1de81d0,
   115  	0xcd8a8dc3, 0x598fac3b, 0x7f08ad04, 0xc5918a94,
   116  	0x930e5ed, 0x5219b4bb, 0xc0514ecd, 0x9c98b265,
   117  	0x66fa667c, 0x89c6527f, 0xdc196f0b, 0x2f4d1517,
   118  	0x665d9a7f, 0x84957ea3, 0x2fbd3b9f, 0x27386031,
   119  	0x2fd82e6, 0xf0871164, 0xc5d6c8d3, 0xb354eebd,
   120  	0xb22d0e03, 0xa16819f4, 0x7c30844, 0x34d389f8,
   121  	0x167b37f7, 0x18aad495, 0x282e87d5, 0xee0735f5,
   122  	0xe4bdb43, 0x23fcca3e, 0x25869e5e, 0x26767c4d,
   123  	0xe64d18e2, 0xe7f34e8c, 0x73db1422, 0xa891cb23,
   124  	0x7b15c684, 0x97ee33dd, 0xb158e6fe, 0xd41444b6,
   125  	0x2d99746, 0xc64fe2cf, 0x28cd996a, 0xf927a83d,
   126  	0x595aa9d5, 0x9718703f, 0xe0816193, 0xebc37486,
   127  	0xa3103dbf, 0x497be667, 0xfd05edcc, 0x711482f9,
   128  	0x71a2b765, 0x54e85ace, 0x25db7088, 0xb6b9940,
   129  	0x270e5f47, 0x98b28b96, 0xafd0c359, 0x8561742,
   130  	0x205040e0, 0xfd7e89a4, 0x5c6ec113, 0xb034b4ea,
   131  	0xc531122a, 0xb7f218b3, 0xb8398b46, 0xfa8a5c1a,
   132  	0xeb61ded2, 0x61d9f92f, 0xd7d83cd7, 0xaf77288d,
   133  	0x82cd4c34, 0xa016f41e, 0x331d0039, 0x1259f138,
   134  	0x2a27efc1, 0xa514b5da, 0x4d234b69, 0xa3432a1a,
   135  	0xeaa7e695, 0x5bd985da, 0x7b7b7b32, 0xaf19f1e9,
   136  	0x35b5820, 0x27c4a359, 0x19a37566, 0xd47b45a9,
   137  	0x85c391b9, 0xb8bef5e5, 0x904933f7, 0x581fd0f8,
   138  	0x894db622, 0xabf7401e, 0xc44d2810, 0xdde29a0e,
   139  	0xaa7e5b42, 0x347910c6, 0x397265c6, 0x5311ace7,
   140  	0xc4d31dd1, 0x2e12518a, 0x2f00875c, 0x253039ed,
   141  	0xeed133b9, 0x520af631, 0xb6986667, 0xb7b8bbad,
   142  	0xa734c957, 0xd13f1939, 0x1e088a04, 0xabab5e4e,
   143  	0x5927da8b, 0x2c4c3749, 0x27c6d1d7, 0x153866ab,
   144  }