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