1*e89516f0SMike Frysinger /* adler32.c -- compute the Adler-32 checksum of a data stream 2*e89516f0SMike Frysinger * Copyright (C) 1995-2004 Mark Adler 3*e89516f0SMike Frysinger * For conditions of distribution and use, see copyright notice in zlib.h 4*e89516f0SMike Frysinger */ 5*e89516f0SMike Frysinger 6*e89516f0SMike Frysinger /* @(#) $Id$ */ 7*e89516f0SMike Frysinger 8*e89516f0SMike Frysinger #define ZLIB_INTERNAL 9*e89516f0SMike Frysinger #include "zlib.h" 10*e89516f0SMike Frysinger 11*e89516f0SMike Frysinger #define BASE 65521UL /* largest prime smaller than 65536 */ 12*e89516f0SMike Frysinger #define NMAX 5552 13*e89516f0SMike Frysinger /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ 14*e89516f0SMike Frysinger 15*e89516f0SMike Frysinger #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} 16*e89516f0SMike Frysinger #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); 17*e89516f0SMike Frysinger #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); 18*e89516f0SMike Frysinger #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); 19*e89516f0SMike Frysinger #define DO16(buf) DO8(buf,0); DO8(buf,8); 20*e89516f0SMike Frysinger 21*e89516f0SMike Frysinger /* use NO_DIVIDE if your processor does not do division in hardware */ 22*e89516f0SMike Frysinger #ifdef NO_DIVIDE 23*e89516f0SMike Frysinger # define MOD(a) \ 24*e89516f0SMike Frysinger do { \ 25*e89516f0SMike Frysinger if (a >= (BASE << 16)) a -= (BASE << 16); \ 26*e89516f0SMike Frysinger if (a >= (BASE << 15)) a -= (BASE << 15); \ 27*e89516f0SMike Frysinger if (a >= (BASE << 14)) a -= (BASE << 14); \ 28*e89516f0SMike Frysinger if (a >= (BASE << 13)) a -= (BASE << 13); \ 29*e89516f0SMike Frysinger if (a >= (BASE << 12)) a -= (BASE << 12); \ 30*e89516f0SMike Frysinger if (a >= (BASE << 11)) a -= (BASE << 11); \ 31*e89516f0SMike Frysinger if (a >= (BASE << 10)) a -= (BASE << 10); \ 32*e89516f0SMike Frysinger if (a >= (BASE << 9)) a -= (BASE << 9); \ 33*e89516f0SMike Frysinger if (a >= (BASE << 8)) a -= (BASE << 8); \ 34*e89516f0SMike Frysinger if (a >= (BASE << 7)) a -= (BASE << 7); \ 35*e89516f0SMike Frysinger if (a >= (BASE << 6)) a -= (BASE << 6); \ 36*e89516f0SMike Frysinger if (a >= (BASE << 5)) a -= (BASE << 5); \ 37*e89516f0SMike Frysinger if (a >= (BASE << 4)) a -= (BASE << 4); \ 38*e89516f0SMike Frysinger if (a >= (BASE << 3)) a -= (BASE << 3); \ 39*e89516f0SMike Frysinger if (a >= (BASE << 2)) a -= (BASE << 2); \ 40*e89516f0SMike Frysinger if (a >= (BASE << 1)) a -= (BASE << 1); \ 41*e89516f0SMike Frysinger if (a >= BASE) a -= BASE; \ 42*e89516f0SMike Frysinger } while (0) 43*e89516f0SMike Frysinger # define MOD4(a) \ 44*e89516f0SMike Frysinger do { \ 45*e89516f0SMike Frysinger if (a >= (BASE << 4)) a -= (BASE << 4); \ 46*e89516f0SMike Frysinger if (a >= (BASE << 3)) a -= (BASE << 3); \ 47*e89516f0SMike Frysinger if (a >= (BASE << 2)) a -= (BASE << 2); \ 48*e89516f0SMike Frysinger if (a >= (BASE << 1)) a -= (BASE << 1); \ 49*e89516f0SMike Frysinger if (a >= BASE) a -= BASE; \ 50*e89516f0SMike Frysinger } while (0) 51*e89516f0SMike Frysinger #else 52*e89516f0SMike Frysinger # define MOD(a) a %= BASE 53*e89516f0SMike Frysinger # define MOD4(a) a %= BASE 54*e89516f0SMike Frysinger #endif 55*e89516f0SMike Frysinger 56*e89516f0SMike Frysinger /* ========================================================================= */ 57*e89516f0SMike Frysinger uLong ZEXPORT adler32(adler, buf, len) 58*e89516f0SMike Frysinger uLong adler; 59*e89516f0SMike Frysinger const Bytef *buf; 60*e89516f0SMike Frysinger uInt len; 61*e89516f0SMike Frysinger { 62*e89516f0SMike Frysinger unsigned long sum2; 63*e89516f0SMike Frysinger unsigned n; 64*e89516f0SMike Frysinger 65*e89516f0SMike Frysinger /* split Adler-32 into component sums */ 66*e89516f0SMike Frysinger sum2 = (adler >> 16) & 0xffff; 67*e89516f0SMike Frysinger adler &= 0xffff; 68*e89516f0SMike Frysinger 69*e89516f0SMike Frysinger /* in case user likes doing a byte at a time, keep it fast */ 70*e89516f0SMike Frysinger if (len == 1) { 71*e89516f0SMike Frysinger adler += buf[0]; 72*e89516f0SMike Frysinger if (adler >= BASE) 73*e89516f0SMike Frysinger adler -= BASE; 74*e89516f0SMike Frysinger sum2 += adler; 75*e89516f0SMike Frysinger if (sum2 >= BASE) 76*e89516f0SMike Frysinger sum2 -= BASE; 77*e89516f0SMike Frysinger return adler | (sum2 << 16); 78*e89516f0SMike Frysinger } 79*e89516f0SMike Frysinger 80*e89516f0SMike Frysinger /* initial Adler-32 value (deferred check for len == 1 speed) */ 81*e89516f0SMike Frysinger if (buf == Z_NULL) 82*e89516f0SMike Frysinger return 1L; 83*e89516f0SMike Frysinger 84*e89516f0SMike Frysinger /* in case short lengths are provided, keep it somewhat fast */ 85*e89516f0SMike Frysinger if (len < 16) { 86*e89516f0SMike Frysinger while (len--) { 87*e89516f0SMike Frysinger adler += *buf++; 88*e89516f0SMike Frysinger sum2 += adler; 89*e89516f0SMike Frysinger } 90*e89516f0SMike Frysinger if (adler >= BASE) 91*e89516f0SMike Frysinger adler -= BASE; 92*e89516f0SMike Frysinger MOD4(sum2); /* only added so many BASE's */ 93*e89516f0SMike Frysinger return adler | (sum2 << 16); 94*e89516f0SMike Frysinger } 95*e89516f0SMike Frysinger 96*e89516f0SMike Frysinger /* do length NMAX blocks -- requires just one modulo operation */ 97*e89516f0SMike Frysinger while (len >= NMAX) { 98*e89516f0SMike Frysinger len -= NMAX; 99*e89516f0SMike Frysinger n = NMAX / 16; /* NMAX is divisible by 16 */ 100*e89516f0SMike Frysinger do { 101*e89516f0SMike Frysinger DO16(buf); /* 16 sums unrolled */ 102*e89516f0SMike Frysinger buf += 16; 103*e89516f0SMike Frysinger } while (--n); 104*e89516f0SMike Frysinger MOD(adler); 105*e89516f0SMike Frysinger MOD(sum2); 106*e89516f0SMike Frysinger } 107*e89516f0SMike Frysinger 108*e89516f0SMike Frysinger /* do remaining bytes (less than NMAX, still just one modulo) */ 109*e89516f0SMike Frysinger if (len) { /* avoid modulos if none remaining */ 110*e89516f0SMike Frysinger while (len >= 16) { 111*e89516f0SMike Frysinger len -= 16; 112*e89516f0SMike Frysinger DO16(buf); 113*e89516f0SMike Frysinger buf += 16; 114*e89516f0SMike Frysinger } 115*e89516f0SMike Frysinger while (len--) { 116*e89516f0SMike Frysinger adler += *buf++; 117*e89516f0SMike Frysinger sum2 += adler; 118*e89516f0SMike Frysinger } 119*e89516f0SMike Frysinger MOD(adler); 120*e89516f0SMike Frysinger MOD(sum2); 121*e89516f0SMike Frysinger } 122*e89516f0SMike Frysinger 123*e89516f0SMike Frysinger /* return recombined sums */ 124*e89516f0SMike Frysinger return adler | (sum2 << 16); 125*e89516f0SMike Frysinger } 126