#include "zutil.h"
#define BASE 65521U /* largest prime smaller than 65536 */
#define NMAX 5552
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
#ifdef NO_DIVIDE
# define CHOP(a) \
do
{ \
unsigned
long
tmp = a >> 16; \
a &= 0xffffUL; \
a += (tmp << 4) - tmp; \
}
while
(0)
# define MOD28(a) \
do
{ \
CHOP(a); \
if
(a >= BASE) a -= BASE; \
}
while
(0)
# define MOD(a) \
do
{ \
CHOP(a); \
MOD28(a); \
}
while
(0)
# define MOD63(a) \
do
{
\
z_off64_t tmp = a >> 32; \
a &= 0xffffffffL; \
a += (tmp << 8) - (tmp << 5) + tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
if
(a >= BASE) a -= BASE; \
}
while
(0)
#else
# define MOD(a) a %= BASE
# define MOD28(a) a %= BASE
# define MOD63(a) a %= BASE
#endif
uLong ZEXPORT adler32_z(uLong adler,
const
Bytef *buf, z_size_t len) {
unsigned
long
sum2;
unsigned n;
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
if
(len == 1) {
adler += buf[0];
if
(adler >= BASE)
adler -= BASE;
sum2 += adler;
if
(sum2 >= BASE)
sum2 -= BASE;
return
adler | (sum2 << 16);
}
if
(buf == Z_NULL)
return
1L;
if
(len < 16) {
while
(len--) {
adler += *buf++;
sum2 += adler;
}
if
(adler >= BASE)
adler -= BASE;
MOD28(sum2);
return
adler | (sum2 << 16);
}
while
(len >= NMAX) {
len -= NMAX;
n = NMAX / 16;
do
{
DO16(buf);
buf += 16;
}
while
(--n);
MOD(adler);
MOD(sum2);
}
if
(len) {
while
(len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while
(len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
return
adler | (sum2 << 16);
}
uLong ZEXPORT adler32(uLong adler,
const
Bytef *buf, uInt len) {
return
adler32_z(adler, buf, len);
}
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
unsigned
long
sum1;
unsigned
long
sum2;
unsigned rem;
if
(len2 < 0)
return
0xffffffffUL;
MOD63(len2);
rem = (unsigned)len2;
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if
(sum1 >= BASE) sum1 -= BASE;
if
(sum1 >= BASE) sum1 -= BASE;
if
(sum2 >= ((unsigned
long
)BASE << 1)) sum2 -= ((unsigned
long
)BASE << 1);
if
(sum2 >= BASE) sum2 -= BASE;
return
sum1 | (sum2 << 16);
}
uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
return
adler32_combine_(adler1, adler2, len2);
}
uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
return
adler32_combine_(adler1, adler2, len2);
}