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