xref: /aosp_15_r20/external/erofs-utils/lib/rolling_hash.h (revision 33b1fccf6a0fada2c2875d400ed01119b7676ee5)
1*33b1fccfSAndroid Build Coastguard Worker /* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */
2*33b1fccfSAndroid Build Coastguard Worker /*
3*33b1fccfSAndroid Build Coastguard Worker  * Copyright (C) 2022 Alibaba Cloud
4*33b1fccfSAndroid Build Coastguard Worker  */
5*33b1fccfSAndroid Build Coastguard Worker #ifndef __ROLLING_HASH_H__
6*33b1fccfSAndroid Build Coastguard Worker #define __ROLLING_HASH_H__
7*33b1fccfSAndroid Build Coastguard Worker 
8*33b1fccfSAndroid Build Coastguard Worker #include <erofs/defs.h>
9*33b1fccfSAndroid Build Coastguard Worker 
10*33b1fccfSAndroid Build Coastguard Worker #define PRIME_NUMBER	4294967295LL
11*33b1fccfSAndroid Build Coastguard Worker #define RADIX		256
12*33b1fccfSAndroid Build Coastguard Worker 
erofs_rolling_hash_init(u8 * input,int len,bool backwards)13*33b1fccfSAndroid Build Coastguard Worker static inline long long erofs_rolling_hash_init(u8 *input,
14*33b1fccfSAndroid Build Coastguard Worker 						int len, bool backwards)
15*33b1fccfSAndroid Build Coastguard Worker {
16*33b1fccfSAndroid Build Coastguard Worker 	long long hash = 0;
17*33b1fccfSAndroid Build Coastguard Worker 
18*33b1fccfSAndroid Build Coastguard Worker 	if (!backwards) {
19*33b1fccfSAndroid Build Coastguard Worker 		int i;
20*33b1fccfSAndroid Build Coastguard Worker 
21*33b1fccfSAndroid Build Coastguard Worker 		for (i = 0; i < len; ++i)
22*33b1fccfSAndroid Build Coastguard Worker 			hash = (RADIX * hash + input[i]) % PRIME_NUMBER;
23*33b1fccfSAndroid Build Coastguard Worker 	} else {
24*33b1fccfSAndroid Build Coastguard Worker 		while (len)
25*33b1fccfSAndroid Build Coastguard Worker 			hash = (RADIX * hash + input[--len]) % PRIME_NUMBER;
26*33b1fccfSAndroid Build Coastguard Worker 	}
27*33b1fccfSAndroid Build Coastguard Worker 	return hash;
28*33b1fccfSAndroid Build Coastguard Worker }
29*33b1fccfSAndroid Build Coastguard Worker 
30*33b1fccfSAndroid Build Coastguard Worker /* RM = R ^ (M-1) % Q */
31*33b1fccfSAndroid Build Coastguard Worker /*
32*33b1fccfSAndroid Build Coastguard Worker  * NOTE: value of "hash" could be negative so we cannot use unsiged types for "hash"
33*33b1fccfSAndroid Build Coastguard Worker  * "long long" is used here and PRIME_NUMBER can be ULONG_MAX
34*33b1fccfSAndroid Build Coastguard Worker  */
erofs_rolling_hash_advance(long long old_hash,unsigned long long RM,u8 to_remove,u8 to_add)35*33b1fccfSAndroid Build Coastguard Worker static inline long long erofs_rolling_hash_advance(long long old_hash,
36*33b1fccfSAndroid Build Coastguard Worker 						   unsigned long long RM,
37*33b1fccfSAndroid Build Coastguard Worker 						   u8 to_remove, u8 to_add)
38*33b1fccfSAndroid Build Coastguard Worker {
39*33b1fccfSAndroid Build Coastguard Worker 	long long hash = old_hash;
40*33b1fccfSAndroid Build Coastguard Worker 	long long to_remove_val = (to_remove * RM) % PRIME_NUMBER;
41*33b1fccfSAndroid Build Coastguard Worker 
42*33b1fccfSAndroid Build Coastguard Worker 	hash = RADIX * (old_hash - to_remove_val) % PRIME_NUMBER;
43*33b1fccfSAndroid Build Coastguard Worker 	hash = (hash + to_add) % PRIME_NUMBER;
44*33b1fccfSAndroid Build Coastguard Worker 
45*33b1fccfSAndroid Build Coastguard Worker 	/* We might get negative value of hash, converting it to positive */
46*33b1fccfSAndroid Build Coastguard Worker 	if (hash < 0)
47*33b1fccfSAndroid Build Coastguard Worker 		hash += PRIME_NUMBER;
48*33b1fccfSAndroid Build Coastguard Worker 	return hash;
49*33b1fccfSAndroid Build Coastguard Worker }
50*33b1fccfSAndroid Build Coastguard Worker 
erofs_rollinghash_calc_rm(int window_size)51*33b1fccfSAndroid Build Coastguard Worker static inline long long erofs_rollinghash_calc_rm(int window_size)
52*33b1fccfSAndroid Build Coastguard Worker {
53*33b1fccfSAndroid Build Coastguard Worker 	int i;
54*33b1fccfSAndroid Build Coastguard Worker 	long long RM = 1;
55*33b1fccfSAndroid Build Coastguard Worker 
56*33b1fccfSAndroid Build Coastguard Worker 	for (i = 0; i < window_size - 1; ++i)
57*33b1fccfSAndroid Build Coastguard Worker 		RM = (RM * RADIX) % PRIME_NUMBER;
58*33b1fccfSAndroid Build Coastguard Worker 	return RM;
59*33b1fccfSAndroid Build Coastguard Worker }
60*33b1fccfSAndroid Build Coastguard Worker #endif
61