public void Calculate(byte[] K, byte[] pwd, byte[] salt, ulong timeCost, ulong nRows, ulong nCols)
        {
            ulong kLength    = (ulong)K.Length;
            ulong pwdLength  = (ulong)pwd.Length;
            ulong saltLength = (ulong)salt.Length;

            ClearSettings();

            ulong ROW_LEN_INT64 = LyraConstants.BLOCK_LEN_INT64 * nCols;
            ulong ROW_LEN_BYTES = ROW_LEN_INT64 * LyraConstants.UINT64_SIZE;

            i           = (int)(nRows * ROW_LEN_BYTES);
            wholeMatrix = new byte[nRows * ROW_LEN_BYTES];
            for (int n = 0; n < wholeMatrix.Length; n++)
            {
                wholeMatrix[n] = 0;
            }

            memMatrix = new MemoryMatrix(wholeMatrix, nRows, nCols);

            ulong nBlocksInput = ((saltLength + pwdLength + 6 * sizeof(ulong)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1;

            var integerParameters  = new[] { kLength, pwdLength, saltLength, timeCost, nRows, nCols };
            var concatedParameters = pwd.Concat(salt).Concat(integerParameters.SelectMany(BitConverter.GetBytes)).ToArray();

            Array.Copy(concatedParameters, wholeMatrix, concatedParameters.Length);
            int firstFreeCellIndexOfWholeMatrix = concatedParameters.Length;

            //Now comes the padding

            wholeMatrix[firstFreeCellIndexOfWholeMatrix] = 0x80;
            firstFreeCellIndexOfWholeMatrix = (int)(nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1);
            wholeMatrix[firstFreeCellIndexOfWholeMatrix] ^= 0x01;

            Initialize();
            RunSetupPhase((int)nBlocksInput, nCols, nRows);
            RunWanderingPhase(timeCost, nCols, nRows);
            RunWrapUpPhase(K);
        }
 public Sponge(ulong[] state, MemoryMatrix memoryMatrix)
 {
     this.state        = state;
     this.memoryMatrix = memoryMatrix;
 }