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