xref: /openbsd/lib/libz/adler32.c (revision a04ea15d)
12af503bcStholo /* adler32.c -- compute the Adler-32 checksum of a data stream
236f395ceStb  * Copyright (C) 1995-2011, 2016 Mark Adler
32af503bcStholo  * For conditions of distribution and use, see copyright notice in zlib.h
42af503bcStholo  */
52af503bcStholo 
636f395ceStb #include "zutil.h"
72af503bcStholo 
836f395ceStb #define BASE 65521U     /* largest prime smaller than 65536 */
92af503bcStholo #define NMAX 5552
102af503bcStholo /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
112af503bcStholo 
12d76b9bfaSmillert #define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
132af503bcStholo #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
142af503bcStholo #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
152af503bcStholo #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
162af503bcStholo #define DO16(buf)   DO8(buf,0); DO8(buf,8);
172af503bcStholo 
1836f395ceStb /* use NO_DIVIDE if your processor does not do division in hardware --
1936f395ceStb    try it both ways to see which is faster */
2085c48e79Shenning #ifdef NO_DIVIDE
2136f395ceStb /* note that this assumes BASE is 65521, where 65536 % 65521 == 15
2236f395ceStb    (thank you to John Reiser for pointing this out) */
2336f395ceStb #  define CHOP(a) \
2485c48e79Shenning     do { \
2536f395ceStb         unsigned long tmp = a >> 16; \
2636f395ceStb         a &= 0xffffUL; \
2736f395ceStb         a += (tmp << 4) - tmp; \
2836f395ceStb     } while (0)
2936f395ceStb #  define MOD28(a) \
3036f395ceStb     do { \
3136f395ceStb         CHOP(a); \
3285c48e79Shenning         if (a >= BASE) a -= BASE; \
3385c48e79Shenning     } while (0)
3436f395ceStb #  define MOD(a) \
35d76b9bfaSmillert     do { \
3636f395ceStb         CHOP(a); \
3736f395ceStb         MOD28(a); \
3836f395ceStb     } while (0)
3936f395ceStb #  define MOD63(a) \
4036f395ceStb     do { /* this assumes a is not negative */ \
4136f395ceStb         z_off64_t tmp = a >> 32; \
4236f395ceStb         a &= 0xffffffffL; \
4336f395ceStb         a += (tmp << 8) - (tmp << 5) + tmp; \
4436f395ceStb         tmp = a >> 16; \
4536f395ceStb         a &= 0xffffL; \
4636f395ceStb         a += (tmp << 4) - tmp; \
4736f395ceStb         tmp = a >> 16; \
4836f395ceStb         a &= 0xffffL; \
4936f395ceStb         a += (tmp << 4) - tmp; \
50d76b9bfaSmillert         if (a >= BASE) a -= BASE; \
51d76b9bfaSmillert     } while (0)
5285c48e79Shenning #else
5385c48e79Shenning #  define MOD(a) a %= BASE
5436f395ceStb #  define MOD28(a) a %= BASE
5536f395ceStb #  define MOD63(a) a %= BASE
5685c48e79Shenning #endif
5785c48e79Shenning 
582af503bcStholo /* ========================================================================= */
adler32_z(uLong adler,const Bytef * buf,z_size_t len)59*a04ea15dStb uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
60d76b9bfaSmillert     unsigned long sum2;
61d76b9bfaSmillert     unsigned n;
622af503bcStholo 
63d76b9bfaSmillert     /* split Adler-32 into component sums */
64d76b9bfaSmillert     sum2 = (adler >> 16) & 0xffff;
65d76b9bfaSmillert     adler &= 0xffff;
662af503bcStholo 
67d76b9bfaSmillert     /* in case user likes doing a byte at a time, keep it fast */
68d76b9bfaSmillert     if (len == 1) {
69d76b9bfaSmillert         adler += buf[0];
70d76b9bfaSmillert         if (adler >= BASE)
71d76b9bfaSmillert             adler -= BASE;
72d76b9bfaSmillert         sum2 += adler;
73d76b9bfaSmillert         if (sum2 >= BASE)
74d76b9bfaSmillert             sum2 -= BASE;
75d76b9bfaSmillert         return adler | (sum2 << 16);
76d76b9bfaSmillert     }
77d76b9bfaSmillert 
78d76b9bfaSmillert     /* initial Adler-32 value (deferred check for len == 1 speed) */
79d76b9bfaSmillert     if (buf == Z_NULL)
80d76b9bfaSmillert         return 1L;
81d76b9bfaSmillert 
82d76b9bfaSmillert     /* in case short lengths are provided, keep it somewhat fast */
83d76b9bfaSmillert     if (len < 16) {
84d76b9bfaSmillert         while (len--) {
85d76b9bfaSmillert             adler += *buf++;
86d76b9bfaSmillert             sum2 += adler;
87d76b9bfaSmillert         }
88d76b9bfaSmillert         if (adler >= BASE)
89d76b9bfaSmillert             adler -= BASE;
9036f395ceStb         MOD28(sum2);            /* only added so many BASE's */
91d76b9bfaSmillert         return adler | (sum2 << 16);
92d76b9bfaSmillert     }
93d76b9bfaSmillert 
94d76b9bfaSmillert     /* do length NMAX blocks -- requires just one modulo operation */
95d76b9bfaSmillert     while (len >= NMAX) {
96d76b9bfaSmillert         len -= NMAX;
97d76b9bfaSmillert         n = NMAX / 16;          /* NMAX is divisible by 16 */
98d76b9bfaSmillert         do {
99d76b9bfaSmillert             DO16(buf);          /* 16 sums unrolled */
100d76b9bfaSmillert             buf += 16;
101d76b9bfaSmillert         } while (--n);
102d76b9bfaSmillert         MOD(adler);
103d76b9bfaSmillert         MOD(sum2);
104d76b9bfaSmillert     }
105d76b9bfaSmillert 
106d76b9bfaSmillert     /* do remaining bytes (less than NMAX, still just one modulo) */
107d76b9bfaSmillert     if (len) {                  /* avoid modulos if none remaining */
108d76b9bfaSmillert         while (len >= 16) {
109d76b9bfaSmillert             len -= 16;
1102af503bcStholo             DO16(buf);
1112af503bcStholo             buf += 16;
1122af503bcStholo         }
113d76b9bfaSmillert         while (len--) {
114d76b9bfaSmillert             adler += *buf++;
115d76b9bfaSmillert             sum2 += adler;
1162af503bcStholo         }
117d76b9bfaSmillert         MOD(adler);
118d76b9bfaSmillert         MOD(sum2);
119d76b9bfaSmillert     }
120d76b9bfaSmillert 
121d76b9bfaSmillert     /* return recombined sums */
122d76b9bfaSmillert     return adler | (sum2 << 16);
123d76b9bfaSmillert }
124d76b9bfaSmillert 
125d76b9bfaSmillert /* ========================================================================= */
adler32(uLong adler,const Bytef * buf,uInt len)126*a04ea15dStb uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
12736f395ceStb     return adler32_z(adler, buf, len);
12836f395ceStb }
12936f395ceStb 
13036f395ceStb /* ========================================================================= */
adler32_combine_(uLong adler1,uLong adler2,z_off64_t len2)131*a04ea15dStb local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
132d76b9bfaSmillert     unsigned long sum1;
133d76b9bfaSmillert     unsigned long sum2;
134d76b9bfaSmillert     unsigned rem;
135d76b9bfaSmillert 
13636f395ceStb     /* for negative len, return invalid adler32 as a clue for debugging */
13736f395ceStb     if (len2 < 0)
13836f395ceStb         return 0xffffffffUL;
13936f395ceStb 
140d76b9bfaSmillert     /* the derivation of this formula is left as an exercise for the reader */
14136f395ceStb     MOD63(len2);                /* assumes len2 >= 0 */
14236f395ceStb     rem = (unsigned)len2;
143d76b9bfaSmillert     sum1 = adler1 & 0xffff;
144d76b9bfaSmillert     sum2 = rem * sum1;
145d76b9bfaSmillert     MOD(sum2);
146d76b9bfaSmillert     sum1 += (adler2 & 0xffff) + BASE - 1;
147d76b9bfaSmillert     sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
14836f395ceStb     if (sum1 >= BASE) sum1 -= BASE;
14936f395ceStb     if (sum1 >= BASE) sum1 -= BASE;
15036f395ceStb     if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
15136f395ceStb     if (sum2 >= BASE) sum2 -= BASE;
152d76b9bfaSmillert     return sum1 | (sum2 << 16);
1532af503bcStholo }
15436f395ceStb 
15536f395ceStb /* ========================================================================= */
adler32_combine(uLong adler1,uLong adler2,z_off_t len2)156*a04ea15dStb uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
15736f395ceStb     return adler32_combine_(adler1, adler2, len2);
15836f395ceStb }
15936f395ceStb 
adler32_combine64(uLong adler1,uLong adler2,z_off64_t len2)160*a04ea15dStb uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
16136f395ceStb     return adler32_combine_(adler1, adler2, len2);
16236f395ceStb }
163