xref: /inferno-os/os/boot/libflate/adler.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include "lib9.h"
2 #include <flate.h>
3 
4 enum
5 {
6 	ADLERITERS	= 5552,	/* max iters before can overflow 32 bits */
7 	ADLERBASE	= 65521 /* largest prime smaller than 65536 */
8 };
9 
10 ulong
11 adler32(ulong adler, void *vbuf, int n)
12 {
13 	ulong s1, s2;
14 	uchar *buf, *ebuf;
15 	int m;
16 
17 	buf = vbuf;
18 	s1 = adler & 0xffff;
19 	s2 = (adler >> 16) & 0xffff;
20 	for(; n >= 16; n -= m){
21 		m = n;
22 		if(m > ADLERITERS)
23 			m = ADLERITERS;
24 		m &= ~15;
25 		for(ebuf = buf + m; buf < ebuf; buf += 16){
26 			s1 += buf[0];
27 			s2 += s1;
28 			s1 += buf[1];
29 			s2 += s1;
30 			s1 += buf[2];
31 			s2 += s1;
32 			s1 += buf[3];
33 			s2 += s1;
34 			s1 += buf[4];
35 			s2 += s1;
36 			s1 += buf[5];
37 			s2 += s1;
38 			s1 += buf[6];
39 			s2 += s1;
40 			s1 += buf[7];
41 			s2 += s1;
42 			s1 += buf[8];
43 			s2 += s1;
44 			s1 += buf[9];
45 			s2 += s1;
46 			s1 += buf[10];
47 			s2 += s1;
48 			s1 += buf[11];
49 			s2 += s1;
50 			s1 += buf[12];
51 			s2 += s1;
52 			s1 += buf[13];
53 			s2 += s1;
54 			s1 += buf[14];
55 			s2 += s1;
56 			s1 += buf[15];
57 			s2 += s1;
58 		}
59 		s1 %= ADLERBASE;
60 		s2 %= ADLERBASE;
61 	}
62 	if(n){
63 		for(ebuf = buf + n; buf < ebuf; buf++){
64 			s1 += buf[0];
65 			s2 += s1;
66 		}
67 		s1 %= ADLERBASE;
68 		s2 %= ADLERBASE;
69 	}
70 	return (s2 << 16) + s1;
71 }
72