1*3aa7d58aSMatthew Dillon /* adler32.c -- compute the Adler-32 checksum of a data stream
2*3aa7d58aSMatthew Dillon * Copyright (C) 1995-2011 Mark Adler
3*3aa7d58aSMatthew Dillon * For conditions of distribution and use, see copyright notice in zlib.h
4*3aa7d58aSMatthew Dillon */
5*3aa7d58aSMatthew Dillon
6*3aa7d58aSMatthew Dillon /* @(#) $Id$ */
7*3aa7d58aSMatthew Dillon
8*3aa7d58aSMatthew Dillon #include "hammer2_zlib_zutil.h"
9*3aa7d58aSMatthew Dillon
10*3aa7d58aSMatthew Dillon #define local static
11*3aa7d58aSMatthew Dillon
12*3aa7d58aSMatthew Dillon //local uLong adler32_combine_ (uLong adler1, uLong adler2, z_off64_t len2);
13*3aa7d58aSMatthew Dillon
14*3aa7d58aSMatthew Dillon #define BASE 65521 /* largest prime smaller than 65536 */
15*3aa7d58aSMatthew Dillon #define NMAX 5552
16*3aa7d58aSMatthew Dillon /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
17*3aa7d58aSMatthew Dillon
18*3aa7d58aSMatthew Dillon #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
19*3aa7d58aSMatthew Dillon #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
20*3aa7d58aSMatthew Dillon #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
21*3aa7d58aSMatthew Dillon #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
22*3aa7d58aSMatthew Dillon #define DO16(buf) DO8(buf,0); DO8(buf,8);
23*3aa7d58aSMatthew Dillon
24*3aa7d58aSMatthew Dillon /* use NO_DIVIDE if your processor does not do division in hardware --
25*3aa7d58aSMatthew Dillon try it both ways to see which is faster */
26*3aa7d58aSMatthew Dillon #ifdef NO_DIVIDE
27*3aa7d58aSMatthew Dillon /* note that this assumes BASE is 65521, where 65536 % 65521 == 15
28*3aa7d58aSMatthew Dillon (thank you to John Reiser for pointing this out) */
29*3aa7d58aSMatthew Dillon # define CHOP(a) \
30*3aa7d58aSMatthew Dillon do { \
31*3aa7d58aSMatthew Dillon unsigned long tmp = a >> 16; \
32*3aa7d58aSMatthew Dillon a &= 0xffffUL; \
33*3aa7d58aSMatthew Dillon a += (tmp << 4) - tmp; \
34*3aa7d58aSMatthew Dillon } while (0)
35*3aa7d58aSMatthew Dillon # define MOD28(a) \
36*3aa7d58aSMatthew Dillon do { \
37*3aa7d58aSMatthew Dillon CHOP(a); \
38*3aa7d58aSMatthew Dillon if (a >= BASE) a -= BASE; \
39*3aa7d58aSMatthew Dillon } while (0)
40*3aa7d58aSMatthew Dillon # define MOD(a) \
41*3aa7d58aSMatthew Dillon do { \
42*3aa7d58aSMatthew Dillon CHOP(a); \
43*3aa7d58aSMatthew Dillon MOD28(a); \
44*3aa7d58aSMatthew Dillon } while (0)
45*3aa7d58aSMatthew Dillon # define MOD63(a) \
46*3aa7d58aSMatthew Dillon do { /* this assumes a is not negative */ \
47*3aa7d58aSMatthew Dillon z_off64_t tmp = a >> 32; \
48*3aa7d58aSMatthew Dillon a &= 0xffffffffL; \
49*3aa7d58aSMatthew Dillon a += (tmp << 8) - (tmp << 5) + tmp; \
50*3aa7d58aSMatthew Dillon tmp = a >> 16; \
51*3aa7d58aSMatthew Dillon a &= 0xffffL; \
52*3aa7d58aSMatthew Dillon a += (tmp << 4) - tmp; \
53*3aa7d58aSMatthew Dillon tmp = a >> 16; \
54*3aa7d58aSMatthew Dillon a &= 0xffffL; \
55*3aa7d58aSMatthew Dillon a += (tmp << 4) - tmp; \
56*3aa7d58aSMatthew Dillon if (a >= BASE) a -= BASE; \
57*3aa7d58aSMatthew Dillon } while (0)
58*3aa7d58aSMatthew Dillon #else
59*3aa7d58aSMatthew Dillon # define MOD(a) a %= BASE
60*3aa7d58aSMatthew Dillon # define MOD28(a) a %= BASE
61*3aa7d58aSMatthew Dillon # define MOD63(a) a %= BASE
62*3aa7d58aSMatthew Dillon #endif
63*3aa7d58aSMatthew Dillon
64*3aa7d58aSMatthew Dillon local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
65*3aa7d58aSMatthew Dillon uLong adler32_combine(uLong adler1, uLong adler2, z_off_t len2);
66*3aa7d58aSMatthew Dillon
67*3aa7d58aSMatthew Dillon /* ========================================================================= */
68*3aa7d58aSMatthew Dillon uLong
adler32(uLong adler,const Bytef * buf,uInt len)69*3aa7d58aSMatthew Dillon adler32(uLong adler, const Bytef *buf, uInt len)
70*3aa7d58aSMatthew Dillon {
71*3aa7d58aSMatthew Dillon unsigned long sum2;
72*3aa7d58aSMatthew Dillon unsigned n;
73*3aa7d58aSMatthew Dillon
74*3aa7d58aSMatthew Dillon /* split Adler-32 into component sums */
75*3aa7d58aSMatthew Dillon sum2 = (adler >> 16) & 0xffff;
76*3aa7d58aSMatthew Dillon adler &= 0xffff;
77*3aa7d58aSMatthew Dillon
78*3aa7d58aSMatthew Dillon /* in case user likes doing a byte at a time, keep it fast */
79*3aa7d58aSMatthew Dillon if (len == 1) {
80*3aa7d58aSMatthew Dillon adler += buf[0];
81*3aa7d58aSMatthew Dillon if (adler >= BASE)
82*3aa7d58aSMatthew Dillon adler -= BASE;
83*3aa7d58aSMatthew Dillon sum2 += adler;
84*3aa7d58aSMatthew Dillon if (sum2 >= BASE)
85*3aa7d58aSMatthew Dillon sum2 -= BASE;
86*3aa7d58aSMatthew Dillon return adler | (sum2 << 16);
87*3aa7d58aSMatthew Dillon }
88*3aa7d58aSMatthew Dillon
89*3aa7d58aSMatthew Dillon /* initial Adler-32 value (deferred check for len == 1 speed) */
90*3aa7d58aSMatthew Dillon if (buf == Z_NULL)
91*3aa7d58aSMatthew Dillon return 1L;
92*3aa7d58aSMatthew Dillon
93*3aa7d58aSMatthew Dillon /* in case short lengths are provided, keep it somewhat fast */
94*3aa7d58aSMatthew Dillon if (len < 16) {
95*3aa7d58aSMatthew Dillon while (len--) {
96*3aa7d58aSMatthew Dillon adler += *buf++;
97*3aa7d58aSMatthew Dillon sum2 += adler;
98*3aa7d58aSMatthew Dillon }
99*3aa7d58aSMatthew Dillon if (adler >= BASE)
100*3aa7d58aSMatthew Dillon adler -= BASE;
101*3aa7d58aSMatthew Dillon MOD28(sum2); /* only added so many BASE's */
102*3aa7d58aSMatthew Dillon return adler | (sum2 << 16);
103*3aa7d58aSMatthew Dillon }
104*3aa7d58aSMatthew Dillon
105*3aa7d58aSMatthew Dillon /* do length NMAX blocks -- requires just one modulo operation */
106*3aa7d58aSMatthew Dillon while (len >= NMAX) {
107*3aa7d58aSMatthew Dillon len -= NMAX;
108*3aa7d58aSMatthew Dillon n = NMAX / 16; /* NMAX is divisible by 16 */
109*3aa7d58aSMatthew Dillon do {
110*3aa7d58aSMatthew Dillon DO16(buf); /* 16 sums unrolled */
111*3aa7d58aSMatthew Dillon buf += 16;
112*3aa7d58aSMatthew Dillon } while (--n);
113*3aa7d58aSMatthew Dillon MOD(adler);
114*3aa7d58aSMatthew Dillon MOD(sum2);
115*3aa7d58aSMatthew Dillon }
116*3aa7d58aSMatthew Dillon
117*3aa7d58aSMatthew Dillon /* do remaining bytes (less than NMAX, still just one modulo) */
118*3aa7d58aSMatthew Dillon if (len) { /* avoid modulos if none remaining */
119*3aa7d58aSMatthew Dillon while (len >= 16) {
120*3aa7d58aSMatthew Dillon len -= 16;
121*3aa7d58aSMatthew Dillon DO16(buf);
122*3aa7d58aSMatthew Dillon buf += 16;
123*3aa7d58aSMatthew Dillon }
124*3aa7d58aSMatthew Dillon while (len--) {
125*3aa7d58aSMatthew Dillon adler += *buf++;
126*3aa7d58aSMatthew Dillon sum2 += adler;
127*3aa7d58aSMatthew Dillon }
128*3aa7d58aSMatthew Dillon MOD(adler);
129*3aa7d58aSMatthew Dillon MOD(sum2);
130*3aa7d58aSMatthew Dillon }
131*3aa7d58aSMatthew Dillon
132*3aa7d58aSMatthew Dillon /* return recombined sums */
133*3aa7d58aSMatthew Dillon return adler | (sum2 << 16);
134*3aa7d58aSMatthew Dillon }
135*3aa7d58aSMatthew Dillon
136*3aa7d58aSMatthew Dillon /* ========================================================================= */
137*3aa7d58aSMatthew Dillon local
138*3aa7d58aSMatthew Dillon uLong
adler32_combine_(uLong adler1,uLong adler2,z_off64_t len2)139*3aa7d58aSMatthew Dillon adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2)
140*3aa7d58aSMatthew Dillon {
141*3aa7d58aSMatthew Dillon unsigned long sum1;
142*3aa7d58aSMatthew Dillon unsigned long sum2;
143*3aa7d58aSMatthew Dillon unsigned rem;
144*3aa7d58aSMatthew Dillon
145*3aa7d58aSMatthew Dillon /* for negative len, return invalid adler32 as a clue for debugging */
146*3aa7d58aSMatthew Dillon if (len2 < 0)
147*3aa7d58aSMatthew Dillon return 0xffffffffUL;
148*3aa7d58aSMatthew Dillon
149*3aa7d58aSMatthew Dillon /* the derivation of this formula is left as an exercise for the reader */
150*3aa7d58aSMatthew Dillon MOD63(len2); /* assumes len2 >= 0 */
151*3aa7d58aSMatthew Dillon rem = (unsigned)len2;
152*3aa7d58aSMatthew Dillon sum1 = adler1 & 0xffff;
153*3aa7d58aSMatthew Dillon sum2 = rem * sum1;
154*3aa7d58aSMatthew Dillon MOD(sum2);
155*3aa7d58aSMatthew Dillon sum1 += (adler2 & 0xffff) + BASE - 1;
156*3aa7d58aSMatthew Dillon sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
157*3aa7d58aSMatthew Dillon if (sum1 >= BASE) sum1 -= BASE;
158*3aa7d58aSMatthew Dillon if (sum1 >= BASE) sum1 -= BASE;
159*3aa7d58aSMatthew Dillon if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
160*3aa7d58aSMatthew Dillon if (sum2 >= BASE) sum2 -= BASE;
161*3aa7d58aSMatthew Dillon return sum1 | (sum2 << 16);
162*3aa7d58aSMatthew Dillon }
163*3aa7d58aSMatthew Dillon
164*3aa7d58aSMatthew Dillon /* ========================================================================= */
165*3aa7d58aSMatthew Dillon uLong
adler32_combine(uLong adler1,uLong adler2,z_off_t len2)166*3aa7d58aSMatthew Dillon adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
167*3aa7d58aSMatthew Dillon {
168*3aa7d58aSMatthew Dillon return adler32_combine_(adler1, adler2, len2);
169*3aa7d58aSMatthew Dillon }
170*3aa7d58aSMatthew Dillon
171*3aa7d58aSMatthew Dillon uLong
adler32_combine64(uLong adler1,uLong adler2,z_off64_t len2)172*3aa7d58aSMatthew Dillon adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2)
173*3aa7d58aSMatthew Dillon {
174*3aa7d58aSMatthew Dillon return adler32_combine_(adler1, adler2, len2);
175*3aa7d58aSMatthew Dillon }
176