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