117651Speter/* adler32.c -- compute the Adler-32 checksum of a data stream
2313796Sdelphij * Copyright (C) 1995-2011, 2016 Mark Adler
3131377Stjr * For conditions of distribution and use, see copyright notice in zlib.h
417651Speter */
517651Speter
633904Ssteve/* @(#) $Id$ */
717651Speter
8205194Sdelphij#include "zutil.h"
917651Speter
10230837Sdelphijlocal uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
11205194Sdelphij
12313796Sdelphij#define BASE 65521U     /* largest prime smaller than 65536 */
1317651Speter#define NMAX 5552
1417651Speter/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
1517651Speter
16157043Sdes#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
1717651Speter#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
1817651Speter#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
1917651Speter#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
2017651Speter#define DO16(buf)   DO8(buf,0); DO8(buf,8);
2117651Speter
22230837Sdelphij/* use NO_DIVIDE if your processor does not do division in hardware --
23230837Sdelphij   try it both ways to see which is faster */
24131377Stjr#ifdef NO_DIVIDE
25230837Sdelphij/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
26230837Sdelphij   (thank you to John Reiser for pointing this out) */
27230837Sdelphij#  define CHOP(a) \
28131377Stjr    do { \
29230837Sdelphij        unsigned long tmp = a >> 16; \
30230837Sdelphij        a &= 0xffffUL; \
31230837Sdelphij        a += (tmp << 4) - tmp; \
32230837Sdelphij    } while (0)
33230837Sdelphij#  define MOD28(a) \
34230837Sdelphij    do { \
35230837Sdelphij        CHOP(a); \
36131377Stjr        if (a >= BASE) a -= BASE; \
37131377Stjr    } while (0)
38230837Sdelphij#  define MOD(a) \
39157043Sdes    do { \
40230837Sdelphij        CHOP(a); \
41230837Sdelphij        MOD28(a); \
42230837Sdelphij    } while (0)
43230837Sdelphij#  define MOD63(a) \
44230837Sdelphij    do { /* this assumes a is not negative */ \
45230837Sdelphij        z_off64_t tmp = a >> 32; \
46230837Sdelphij        a &= 0xffffffffL; \
47230837Sdelphij        a += (tmp << 8) - (tmp << 5) + tmp; \
48230837Sdelphij        tmp = a >> 16; \
49230837Sdelphij        a &= 0xffffL; \
50230837Sdelphij        a += (tmp << 4) - tmp; \
51230837Sdelphij        tmp = a >> 16; \
52230837Sdelphij        a &= 0xffffL; \
53230837Sdelphij        a += (tmp << 4) - tmp; \
54157043Sdes        if (a >= BASE) a -= BASE; \
55157043Sdes    } while (0)
56131377Stjr#else
57131377Stjr#  define MOD(a) a %= BASE
58230837Sdelphij#  define MOD28(a) a %= BASE
59230837Sdelphij#  define MOD63(a) a %= BASE
60131377Stjr#endif
61131377Stjr
6217651Speter/* ========================================================================= */
63313796SdelphijuLong ZEXPORT adler32_z(adler, buf, len)
6417651Speter    uLong adler;
6517651Speter    const Bytef *buf;
66313796Sdelphij    z_size_t len;
6717651Speter{
68157043Sdes    unsigned long sum2;
69157043Sdes    unsigned n;
7017651Speter
71157043Sdes    /* split Adler-32 into component sums */
72157043Sdes    sum2 = (adler >> 16) & 0xffff;
73157043Sdes    adler &= 0xffff;
7417651Speter
75157043Sdes    /* in case user likes doing a byte at a time, keep it fast */
76157043Sdes    if (len == 1) {
77157043Sdes        adler += buf[0];
78157043Sdes        if (adler >= BASE)
79157043Sdes            adler -= BASE;
80157043Sdes        sum2 += adler;
81157043Sdes        if (sum2 >= BASE)
82157043Sdes            sum2 -= BASE;
83157043Sdes        return adler | (sum2 << 16);
84157043Sdes    }
85157043Sdes
86157043Sdes    /* initial Adler-32 value (deferred check for len == 1 speed) */
87157043Sdes    if (buf == Z_NULL)
88157043Sdes        return 1L;
89157043Sdes
90157043Sdes    /* in case short lengths are provided, keep it somewhat fast */
91157043Sdes    if (len < 16) {
92157043Sdes        while (len--) {
93157043Sdes            adler += *buf++;
94157043Sdes            sum2 += adler;
95157043Sdes        }
96157043Sdes        if (adler >= BASE)
97157043Sdes            adler -= BASE;
98230837Sdelphij        MOD28(sum2);            /* only added so many BASE's */
99157043Sdes        return adler | (sum2 << 16);
100157043Sdes    }
101157043Sdes
102157043Sdes    /* do length NMAX blocks -- requires just one modulo operation */
103157043Sdes    while (len >= NMAX) {
104157043Sdes        len -= NMAX;
105157043Sdes        n = NMAX / 16;          /* NMAX is divisible by 16 */
106157043Sdes        do {
107157043Sdes            DO16(buf);          /* 16 sums unrolled */
108157043Sdes            buf += 16;
109157043Sdes        } while (--n);
110157043Sdes        MOD(adler);
111157043Sdes        MOD(sum2);
112157043Sdes    }
113157043Sdes
114157043Sdes    /* do remaining bytes (less than NMAX, still just one modulo) */
115157043Sdes    if (len) {                  /* avoid modulos if none remaining */
116157043Sdes        while (len >= 16) {
117157043Sdes            len -= 16;
11817651Speter            DO16(buf);
119131377Stjr            buf += 16;
12017651Speter        }
121157043Sdes        while (len--) {
122157043Sdes            adler += *buf++;
123157043Sdes            sum2 += adler;
124157043Sdes        }
125157043Sdes        MOD(adler);
126157043Sdes        MOD(sum2);
12717651Speter    }
128157043Sdes
129157043Sdes    /* return recombined sums */
130157043Sdes    return adler | (sum2 << 16);
13117651Speter}
132157043Sdes
133157043Sdes/* ========================================================================= */
134313796SdelphijuLong ZEXPORT adler32(adler, buf, len)
135313796Sdelphij    uLong adler;
136313796Sdelphij    const Bytef *buf;
137313796Sdelphij    uInt len;
138313796Sdelphij{
139313796Sdelphij    return adler32_z(adler, buf, len);
140313796Sdelphij}
141313796Sdelphij
142313796Sdelphij/* ========================================================================= */
143205194Sdelphijlocal uLong adler32_combine_(adler1, adler2, len2)
144157043Sdes    uLong adler1;
145157043Sdes    uLong adler2;
146205194Sdelphij    z_off64_t len2;
147157043Sdes{
148157043Sdes    unsigned long sum1;
149157043Sdes    unsigned long sum2;
150157043Sdes    unsigned rem;
151157043Sdes
152230837Sdelphij    /* for negative len, return invalid adler32 as a clue for debugging */
153230837Sdelphij    if (len2 < 0)
154230837Sdelphij        return 0xffffffffUL;
155230837Sdelphij
156157043Sdes    /* the derivation of this formula is left as an exercise for the reader */
157230837Sdelphij    MOD63(len2);                /* assumes len2 >= 0 */
158230837Sdelphij    rem = (unsigned)len2;
159157043Sdes    sum1 = adler1 & 0xffff;
160157043Sdes    sum2 = rem * sum1;
161157043Sdes    MOD(sum2);
162157043Sdes    sum1 += (adler2 & 0xffff) + BASE - 1;
163157043Sdes    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
164205194Sdelphij    if (sum1 >= BASE) sum1 -= BASE;
165205194Sdelphij    if (sum1 >= BASE) sum1 -= BASE;
166313796Sdelphij    if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
167205194Sdelphij    if (sum2 >= BASE) sum2 -= BASE;
168157043Sdes    return sum1 | (sum2 << 16);
169157043Sdes}
170205194Sdelphij
171205194Sdelphij/* ========================================================================= */
172205194SdelphijuLong ZEXPORT adler32_combine(adler1, adler2, len2)
173205194Sdelphij    uLong adler1;
174205194Sdelphij    uLong adler2;
175205194Sdelphij    z_off_t len2;
176205194Sdelphij{
177205194Sdelphij    return adler32_combine_(adler1, adler2, len2);
178205194Sdelphij}
179205194Sdelphij
180205194SdelphijuLong ZEXPORT adler32_combine64(adler1, adler2, len2)
181205194Sdelphij    uLong adler1;
182205194Sdelphij    uLong adler2;
183205194Sdelphij    z_off64_t len2;
184205194Sdelphij{
185205194Sdelphij    return adler32_combine_(adler1, adler2, len2);
186205194Sdelphij}
187