ctypes - Using zlib crc32_combine in Python -
i trying use crc32_combine
function zlib in python. although various other zlib functions available, 1 isn't part of "batteries included" standard library. i've tried 2 approaches: port c code python , calling zlib python ctypes. both give me different results, although not result i'm expecting. i'm presenting ctypes code since think executes faster , has smaller chance additional programmer errors.
the algorithm can combine 2 crc32 hashes when length of data of second hash provided. crc32_combine defined follows:
crc32(crc32(0, seq1, len1), seq2, len2) == crc32_combine( crc32(0, seq1, len1), crc32(0, seq2, len2), len2)
this output:
expected crc: 45e57586 combined crc: 567ee4e4
the second line different when ran python 3.5.1 on win32. not python 2, result never expect either. put zlib1.dll in same directory script try out.
import zlib def crc32_combine_ctypes(crc1, crc2, len2): import ctypes ctypes import util lib = util.find_library('zlib1') _zlib = ctypes.cdll(lib) assert _zlib._name, "can't find zlib" _zlib.crc32_combine.argtypes = [ ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong] _zlib.crc32_combine.restype = ctypes.c_ulong return _zlib.crc32_combine(crc1, crc2, len2) testfile = "zlib1.dll" open(testfile, "rb") tf: data = tf.read() print("expected crc: %0.8x" % (zlib.crc32(data) & 0xffffffff)) cut = len(data) // 2 - 100 p1 = data[0:cut] p2 = data[cut:] crc1 = zlib.crc32(p1) crc2 = zlib.crc32(p2) len1 = len(p1) len2 = len(p2) combined = crc32_combine_ctypes(crc1, crc2, len2) print("combined crc: %0.8x" % (combined & 0xffffffff))
what doing wrong?
eryksun had right idea: used bad , old dll.
my port pure python code couple hundred times slower calling library ctypes. (numbers using timeit 1k iterations , 50m length parameter)
31.729 (function provided below) 0.120 (just _zlib.crc32_combine() call: no library loading included)
the pure python code:
def crc32_combine(crc1, crc2, len2): """explanation algorithm: https://stackoverflow.com/a/23126768/654160 crc32(crc32(0, seq1, len1), seq2, len2) == crc32_combine( crc32(0, seq1, len1), crc32(0, seq2, len2), len2)""" # degenerate case (also disallow negative lengths) if len2 <= 0: return crc1 # put operator 1 0 bit in odd # crc-32 polynomial, 1, 2, 4, 8, ..., 1073741824 odd = [0xedb88320] + [1 << in range(0, 31)] = [0] * 32 def matrix_times(matrix, vector): number_sum = 0 matrix_index = 0 while vector != 0: if vector & 1: number_sum ^= matrix[matrix_index] vector = vector >> 1 & 0x7fffffff matrix_index += 1 return number_sum # put operator 2 0 bits in - gf2_matrix_square(even, odd) even[:] = [matrix_times(odd, odd[n]) n in range(0, 32)] # put operator 4 0 bits in odd odd[:] = [matrix_times(even, even[n]) n in range(0, 32)] # apply len2 zeros crc1 (first square put operator 1 # 0 byte, 8 0 bits, in even) while len2 != 0: # apply zeros operator bit of len2 even[:] = [matrix_times(odd, odd[n]) n in range(0, 32)] if len2 & 1: crc1 = matrix_times(even, crc1) len2 >>= 1 # if no more bits set, done if len2 == 0: break # iteration of loop odd , swapped odd[:] = [matrix_times(even, even[n]) n in range(0, 32)] if len2 & 1: crc1 = matrix_times(odd, crc1) len2 >>= 1 # if no more bits set, done # return combined crc crc1 ^= crc2 return crc1
Comments
Post a Comment