xref: /inferno-os/os/boot/libflate/adler.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
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