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