docs: private static int[] calculate(byte[] data) {
      int A = 0x67452301;
      int B = 0xEFCDAB89;
      int C = 0x98BADCFE;
      int D = 0x10325476;
      int E = 0xC3D2E1F0;
  
      int[] W = new int[80]; // working buffer
      int len = data.length;
      int off = 0;
      int   X, i, n = len/4;
  
      boolean done = false;
      boolean padded = false;
  
      while( !done ) {
        // Fill W array
        for(i=0; (i<16) && (n > 0); n--, off+=4)
          W[i++] = (data[off+3] & 0xFF) | ((data[off+2] & 0xFF) << 8) |
            ((data[off+1] & 0xFF) << 16) | ((data[off] & 0xFF) << 24);
  
        if (i < 16) {             // pad
          if( !padded ) {         // first time past end of data
            X=len%4;
            int pad1 = 0;
            for (int j = 0; j < X; ++j) {
              pad1 |= ((int) (data[off + j] & 0xFF)) << (24 - 8 * j);
            }
            W[i++] = pad1 | (1 << (31 - X * 8));
  //            W[i++] = (X!=0)?(((int)msbf(data,off,X)<<((4-X)*8))|(1<<(31-X*8))):(1<<31);
            if (i==15) W[15]=0;   // 64 bit length of data as bits can't fit
            padded = true;        // don't pad again if there is another iteration
          }
          if (i <= 14) {          // last iteration
            while( i<14 ) W[i++] = 0;
            // bit count = len*8
            W[14] = len >>> 29;
            W[15] = len << 3;
            done = true;
          }
          i = 16;
        }
  
        do {
          W[i] = ((X = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]) << 1) | (X >>> 31);
        } while(++i<80);
  
        // Transform
        int A0 = A;
        int B0 = B;
        int C0 = C;
        int D0 = D;
        int E0 = E;
        i = 0;
        do { X=((A<<5)|(A>>>27))+((B&C)|(~B&D))+E+W[i]+0x5A827999;
        E=D;D=C;C=(B<<30)|(B>>>2);B=A;A=X; } while(++i<20);
        do { X=((A<<5)|(A>>>27))+(B^C^D)+E+W[i]+0x6ED9EBA1;
        E=D;D=C;C=(B<<30)|(B>>>2);B=A;A=X; } while(++i<40);
        do { X=((A<<5)|(A>>>27))+((B&C)|(B&D)|(C&D))+E+W[i]+0x8F1BBCDC;
        E=D;D=C;C=(B<<30)|(B>>>2);B=A;A=X; } while(++i<60);
        do { X=((A<<5)|(A>>>27))+(B^C^D)+E+W[i]+0xCA62C1D6;
        E=D;D=C;C=(B<<30)|(B>>>2);B=A;A=X; } while(++i<80);
        A += A0;
        B += B0;
        C += C0;
        D += D0;
        E += E0;
      }
  
      int[] result = {A, B, C, D, E};
      return result;
    }