#ifndef _RABINKARP_H_
# define _RABINKARP_H_
# include <stddef.h>
# include <stdint.h>
# define RABINKARP_SEED 1
# define RABINKARP_MULT 0x08104225
# define RABINKARP_INVM 0x98f009ad
# define RABINKARP_ADJ 0x08104224
typedef struct _rabinkarp {
size_t count;
uint32_t hash;
uint32_t mult;
} rabinkarp_t;
static inline uint32_t uint32_pow(uint32_t m, size_t p)
{
uint32_t ans = 1;
while (p) {
if (p & 1) {
ans *= m;
}
m *= m;
p >>= 1;
}
return ans;
}
static inline void rabinkarp_init(rabinkarp_t *sum)
{
sum->count = 0;
sum->hash = RABINKARP_SEED;
sum->mult = 1;
}
static inline void rabinkarp_update(rabinkarp_t *sum, const unsigned char *buf,
size_t len)
{
for (size_t i = len; i; i--) {
sum->hash = sum->hash * RABINKARP_MULT + *buf++;
}
sum->count += len;
sum->mult *= uint32_pow(RABINKARP_MULT, len);
}
static inline void rabinkarp_rotate(rabinkarp_t *sum, unsigned char out,
unsigned char in)
{
sum->hash =
sum->hash * RABINKARP_MULT + in - sum->mult * (out + RABINKARP_ADJ);
}
static inline void rabinkarp_rollin(rabinkarp_t *sum, unsigned char in)
{
sum->hash = sum->hash * RABINKARP_MULT + in;
sum->count++;
sum->mult *= RABINKARP_MULT;
}
static inline void rabinkarp_rollout(rabinkarp_t *sum, unsigned char out)
{
sum->count--;
sum->mult *= RABINKARP_INVM;
sum->hash -= sum->mult * (out + RABINKARP_ADJ);
}
static inline uint32_t rabinkarp_digest(rabinkarp_t *sum)
{
return sum->hash;
}
#endif