117651Speter/* adler32.c -- compute the Adler-32 checksum of a data stream
2237410Sdelphij * Copyright (C) 1995-2011 Mark Adler
3131380Stjr * For conditions of distribution and use, see copyright notice in zlib.h
417651Speter */
517651Speter
6146081Skientzle/* @(#) $Id$ */
717651Speter
8205471Sdelphij#include "zutil.h"
917651Speter
10205471Sdelphij#define local static
11205471Sdelphij
12237410Sdelphijlocal uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
13205471Sdelphij
14237410Sdelphij#define BASE 65521      /* largest prime smaller than 65536 */
1517651Speter#define NMAX 5552
1617651Speter/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
1717651Speter
18157046Sdes#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
1917651Speter#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
2017651Speter#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
2117651Speter#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
2217651Speter#define DO16(buf)   DO8(buf,0); DO8(buf,8);
2317651Speter
24237410Sdelphij/* use NO_DIVIDE if your processor does not do division in hardware --
25237410Sdelphij   try it both ways to see which is faster */
26131380Stjr#ifdef NO_DIVIDE
27237410Sdelphij/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
28237410Sdelphij   (thank you to John Reiser for pointing this out) */
29237410Sdelphij#  define CHOP(a) \
30131380Stjr    do { \
31237410Sdelphij        unsigned long tmp = a >> 16; \
32237410Sdelphij        a &= 0xffffUL; \
33237410Sdelphij        a += (tmp << 4) - tmp; \
34237410Sdelphij    } while (0)
35237410Sdelphij#  define MOD28(a) \
36237410Sdelphij    do { \
37237410Sdelphij        CHOP(a); \
38131380Stjr        if (a >= BASE) a -= BASE; \
39131380Stjr    } while (0)
40237410Sdelphij#  define MOD(a) \
41157046Sdes    do { \
42237410Sdelphij        CHOP(a); \
43237410Sdelphij        MOD28(a); \
44237410Sdelphij    } while (0)
45237410Sdelphij#  define MOD63(a) \
46237410Sdelphij    do { /* this assumes a is not negative */ \
47237410Sdelphij        z_off64_t tmp = a >> 32; \
48237410Sdelphij        a &= 0xffffffffL; \
49237410Sdelphij        a += (tmp << 8) - (tmp << 5) + tmp; \
50237410Sdelphij        tmp = a >> 16; \
51237410Sdelphij        a &= 0xffffL; \
52237410Sdelphij        a += (tmp << 4) - tmp; \
53237410Sdelphij        tmp = a >> 16; \
54237410Sdelphij        a &= 0xffffL; \
55237410Sdelphij        a += (tmp << 4) - tmp; \
56157046Sdes        if (a >= BASE) a -= BASE; \
57157046Sdes    } while (0)
58131380Stjr#else
59131380Stjr#  define MOD(a) a %= BASE
60237410Sdelphij#  define MOD28(a) a %= BASE
61237410Sdelphij#  define MOD63(a) a %= BASE
62131380Stjr#endif
63131380Stjr
6417651Speter/* ========================================================================= */
6533908SsteveuLong ZEXPORT adler32(adler, buf, len)
6617651Speter    uLong adler;
6717651Speter    const Bytef *buf;
6817651Speter    uInt len;
6917651Speter{
70157046Sdes    unsigned long sum2;
71157046Sdes    unsigned n;
7217651Speter
73157046Sdes    /* split Adler-32 into component sums */
74157046Sdes    sum2 = (adler >> 16) & 0xffff;
75157046Sdes    adler &= 0xffff;
7617651Speter
77157046Sdes    /* in case user likes doing a byte at a time, keep it fast */
78157046Sdes    if (len == 1) {
79157046Sdes        adler += buf[0];
80157046Sdes        if (adler >= BASE)
81157046Sdes            adler -= BASE;
82157046Sdes        sum2 += adler;
83157046Sdes        if (sum2 >= BASE)
84157046Sdes            sum2 -= BASE;
85157046Sdes        return adler | (sum2 << 16);
86157046Sdes    }
87157046Sdes
88157046Sdes    /* initial Adler-32 value (deferred check for len == 1 speed) */
89157046Sdes    if (buf == Z_NULL)
90157046Sdes        return 1L;
91157046Sdes
92157046Sdes    /* in case short lengths are provided, keep it somewhat fast */
93157046Sdes    if (len < 16) {
94157046Sdes        while (len--) {
95157046Sdes            adler += *buf++;
96157046Sdes            sum2 += adler;
97157046Sdes        }
98157046Sdes        if (adler >= BASE)
99157046Sdes            adler -= BASE;
100237410Sdelphij        MOD28(sum2);            /* only added so many BASE's */
101157046Sdes        return adler | (sum2 << 16);
102157046Sdes    }
103157046Sdes
104157046Sdes    /* do length NMAX blocks -- requires just one modulo operation */
105157046Sdes    while (len >= NMAX) {
106157046Sdes        len -= NMAX;
107157046Sdes        n = NMAX / 16;          /* NMAX is divisible by 16 */
108157046Sdes        do {
109157046Sdes            DO16(buf);          /* 16 sums unrolled */
110157046Sdes            buf += 16;
111157046Sdes        } while (--n);
112157046Sdes        MOD(adler);
113157046Sdes        MOD(sum2);
114157046Sdes    }
115157046Sdes
116157046Sdes    /* do remaining bytes (less than NMAX, still just one modulo) */
117157046Sdes    if (len) {                  /* avoid modulos if none remaining */
118157046Sdes        while (len >= 16) {
119157046Sdes            len -= 16;
12017651Speter            DO16(buf);
121131380Stjr            buf += 16;
12217651Speter        }
123157046Sdes        while (len--) {
124157046Sdes            adler += *buf++;
125157046Sdes            sum2 += adler;
126157046Sdes        }
127157046Sdes        MOD(adler);
128157046Sdes        MOD(sum2);
12917651Speter    }
130157046Sdes
131157046Sdes    /* return recombined sums */
132157046Sdes    return adler | (sum2 << 16);
13317651Speter}
134157046Sdes
135157046Sdes/* ========================================================================= */
136205471Sdelphijlocal uLong adler32_combine_(adler1, adler2, len2)
137157046Sdes    uLong adler1;
138157046Sdes    uLong adler2;
139205471Sdelphij    z_off64_t len2;
140157046Sdes{
141157046Sdes    unsigned long sum1;
142157046Sdes    unsigned long sum2;
143157046Sdes    unsigned rem;
144157046Sdes
145237410Sdelphij    /* for negative len, return invalid adler32 as a clue for debugging */
146237410Sdelphij    if (len2 < 0)
147237410Sdelphij        return 0xffffffffUL;
148237410Sdelphij
149157046Sdes    /* the derivation of this formula is left as an exercise for the reader */
150237410Sdelphij    MOD63(len2);                /* assumes len2 >= 0 */
151237410Sdelphij    rem = (unsigned)len2;
152157046Sdes    sum1 = adler1 & 0xffff;
153157046Sdes    sum2 = rem * sum1;
154157046Sdes    MOD(sum2);
155157046Sdes    sum1 += (adler2 & 0xffff) + BASE - 1;
156157046Sdes    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
157205471Sdelphij    if (sum1 >= BASE) sum1 -= BASE;
158205471Sdelphij    if (sum1 >= BASE) sum1 -= BASE;
159205471Sdelphij    if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
160205471Sdelphij    if (sum2 >= BASE) sum2 -= BASE;
161157046Sdes    return sum1 | (sum2 << 16);
162157046Sdes}
163205471Sdelphij
164205471Sdelphij/* ========================================================================= */
165205471SdelphijuLong ZEXPORT adler32_combine(adler1, adler2, len2)
166205471Sdelphij    uLong adler1;
167205471Sdelphij    uLong adler2;
168205471Sdelphij    z_off_t len2;
169205471Sdelphij{
170205471Sdelphij    return adler32_combine_(adler1, adler2, len2);
171205471Sdelphij}
172205471Sdelphij
173205471SdelphijuLong ZEXPORT adler32_combine64(adler1, adler2, len2)
174205471Sdelphij    uLong adler1;
175205471Sdelphij    uLong adler2;
176205471Sdelphij    z_off64_t len2;
177205471Sdelphij{
178205471Sdelphij    return adler32_combine_(adler1, adler2, len2);
179205471Sdelphij}
180