CRC32: PB (v4) is fast! - thanks!

For everything that's not in any way related to PureBasic. General chat etc...
sverson
Enthusiast
Enthusiast
Posts: 286
Joined: Sun Jul 04, 2004 12:15 pm
Location: Germany

CRC32: PB (v4) is fast! - thanks!

Post by sverson »

Image

Checksum.pb:

Code: Select all

;{/ CRC32: Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43376
;/ CRC32 - a relatively fast algorithm that creates a 32-bit CheckSum.
;}/ CRC32 is the most commonly-used 32-bit CheckSum algorithm.
Procedure.l CRC32d(Buffer.l, BufLen.l)
  !MOV Esi, dword [p.v_Buffer] ;esi = ptr to buffer
  !MOV Edi, dword [p.v_BufLen] ;edi = length of buffer 
  !MOV Ecx, -1                 ;ecx = -1 
  !MOV Edx, Ecx                ;edx = -1 
  !_crc321:                    ;"nextbyte" next byte from buffer
  !XOR Eax, Eax                ;eax = 0 
  !XOR Ebx, Ebx                ;ebx = 0 
  !DB 0xAC                     ;"lodsb" instruction to get next byte
  !XOR al, cl                  ;xor al with cl 
  !MOV cl, ch                  ;cl = ch 
  !MOV ch, dl                  ;ch = dl 
  !MOV dl, dh                  ;dl = dh
  !MOV dh, 8                   ;dh = 8 
  !_crc322:                    ;"nextbit" next bit in the byte
  !SHR bx, 1                   ;shift bits in bx right by 1 
  !RCR ax, 1                   ;(rotate through carry) bits in ax by 1 
  !JNC near _crc323            ;jump to "nocarry" if carry flag not set 
  !XOR ax, 0x08320             ;xor ax with 33568 
  !XOR bx, 0x0EDB8             ;xor bx with 60856
  !_crc323:                    ;"nocarry" if carry flag wasn't set
  !DEC dh                      ;dh = dh - 1 
  !JNZ near _crc322            ;if dh isnt zero, jump to "nextbit" 
  !XOR Ecx, Eax                ;xor ecx with eax 
  !XOR Edx, Ebx                ;xor edx with ebx 
  !DEC Edi                     ;finished with that byte, decrement counter 
  !JNZ near _crc321            ;if edi counter isnt at 0, jump to "nextbyte" 
  !NOT Edx                     ;invert edx bits - 1s complement 
  !NOT Ecx                     ;invert ecx bits - 1s complement 
  !MOV Eax, Edx                ;mov edx into eax 
  !ROL Eax, 16                 ;rotate bits in eax left by 16 places 
  !MOV ax, cx                  ;mov cx into ax 
  ProcedureReturn
EndProcedure

;{/ CRC32: Translated To PureBasic by El_Choni / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=12348
;/ CRC32 - Calculate a CCITT 32-bit For a buffer
;}/ Copyright (c) 1998 by PowerBASIC, Inc.
Procedure.l CRC32e(Address.l, length.l, Seed.l=-1)
  !MOV Edi, dword [p.v_Address] ; address in EDI
  !MOV Ecx, dword [p.v_length]  ; length in ecx
  !JECXZ CrcDone                ; exit is zero length
  !CLD                          ; clear the direction flag
  !BuildCRC:
  !MOVZX Ebx, byte [Edi]        ; get a char
  !MOV ax, word [p.v_Seed+1]    ; get 2nd and 3rd bytes of seed
  !XOR dx, dx                   ; clear DX
  !MOV dl, byte [p.v_Seed+3]    ; get 4th byte of seed
  !XOR bl, byte [p.v_Seed]      ; xor char against first byte of seed
  !XOR bh, bh                   ; clear BH
  !SHL bx, 2                    ; shift the index
  !XOR ax, [CrcTable+Ebx]       ; xor low-half against the table
  !XOR dx, [CrcTable+Ebx+2]     ; xor high-half against the table
  !MOV word [p.v_Seed], ax      ; save the result
  !MOV word [p.v_Seed+2], dx    ; ...
  !INC Edi                      ; move to next char
  !LOOP BuildCRC                ; do ECX times
  !CrcDone:
  !MOV Eax, dword [p.v_Seed]    ; move the result to EAX
  !XOR Eax, -1                  ; compute PKZIP/ZMODEM compatible CRC result
  ProcedureReturn
  DataSection ;{/ CrcTable
  !CrcTable: 
  !DD $000000000, $077073096, $0EE0E612C, $0990951BA
  !DD $0076DC419, $0706AF48F, $0E963A535, $09E6495A3
  !DD $00EDB8832, $079DCB8A4, $0E0D5E91E, $097D2D988
  !DD $009B64C2B, $07EB17CBD, $0E7B82D07, $090BF1D91
  !DD $01DB71064, $06AB020F2, $0F3B97148, $084BE41DE
  !DD $01ADAD47D, $06DDDE4EB, $0F4D4B551, $083D385C7
  !DD $0136C9856, $0646BA8C0, $0FD62F97A, $08A65C9EC
  !DD $014015C4F, $063066CD9, $0FA0F3D63, $08D080DF5
  !DD $03B6E20C8, $04C69105E, $0D56041E4, $0A2677172
  !DD $03C03E4D1, $04B04D447, $0D20D85FD, $0A50AB56B
  !DD $035B5A8FA, $042B2986C, $0DBBBC9D6, $0ACBCF940
  !DD $032D86CE3, $045DF5C75, $0DCD60DCF, $0ABD13D59
  !DD $026D930AC, $051DE003A, $0C8D75180, $0BFD06116
  !DD $021B4F4B5, $056B3C423, $0CFBA9599, $0B8BDA50F
  !DD $02802B89E, $05F058808, $0C60CD9B2, $0B10BE924
  !DD $02F6F7C87, $058684C11, $0C1611DAB, $0B6662D3D
  !DD $076DC4190, $001DB7106, $098D220BC, $0EFD5102A
  !DD $071B18589, $006B6B51F, $09FBFE4A5, $0E8B8D433
  !DD $07807C9A2, $00F00F934, $09609A88E, $0E10E9818
  !DD $07F6A0DBB, $0086D3D2D, $091646C97, $0E6635C01
  !DD $06B6B51F4, $01C6C6162, $0856530D8, $0F262004E
  !DD $06C0695ED, $01B01A57B, $08208F4C1, $0F50FC457
  !DD $065B0D9C6, $012B7E950, $08BBEB8EA, $0FCB9887C
  !DD $062DD1DDF, $015DA2D49, $08CD37CF3, $0FBD44C65
  !DD $04DB26158, $03AB551CE, $0A3BC0074, $0D4BB30E2
  !DD $04ADFA541, $03DD895D7, $0A4D1C46D, $0D3D6F4FB
  !DD $04369E96A, $0346ED9FC, $0AD678846, $0DA60B8D0
  !DD $044042D73, $033031DE5, $0AA0A4C5F, $0DD0D7CC9
  !DD $05005713C, $0270241AA, $0BE0B1010, $0C90C2086
  !DD $05768B525, $0206F85B3, $0B966D409, $0CE61E49F
  !DD $05EDEF90E, $029D9C998, $0B0D09822, $0C7D7A8B4
  !DD $059B33D17, $02EB40D81, $0B7BD5C3B, $0C0BA6CAD
  !DD $0EDB88320, $09ABFB3B6, $003B6E20C, $074B1D29A
  !DD $0EAD54739, $09DD277AF, $004DB2615, $073DC1683
  !DD $0E3630B12, $094643B84, $00D6D6A3E, $07A6A5AA8
  !DD $0E40ECF0B, $09309FF9D, $00A00AE27, $07D079EB1
  !DD $0F00F9344, $08708A3D2, $01E01F268, $06906C2FE
  !DD $0F762575D, $0806567CB, $0196C3671, $06E6B06E7
  !DD $0FED41B76, $089D32BE0, $010DA7A5A, $067DD4ACC
  !DD $0F9B9DF6F, $08EBEEFF9, $017B7BE43, $060B08ED5
  !DD $0D6D6A3E8, $0A1D1937E, $038D8C2C4, $04FDFF252
  !DD $0D1BB67F1, $0A6BC5767, $03FB506DD, $048B2364B
  !DD $0D80D2BDA, $0AF0A1B4C, $036034AF6, $041047A60
  !DD $0DF60EFC3, $0A867DF55, $0316E8EEF, $04669BE79
  !DD $0CB61B38C, $0BC66831A, $0256FD2A0, $05268E236
  !DD $0CC0C7795, $0BB0B4703, $0220216B9, $05505262F
  !DD $0C5BA3BBE, $0B2BD0B28, $02BB45A92, $05CB36A04
  !DD $0C2D7FFA7, $0B5D0CF31, $02CD99E8B, $05BDEAE1D
  !DD $09B64C2B0, $0EC63F226, $0756AA39C, $0026D930A
  !DD $09C0906A9, $0EB0E363F, $072076785, $005005713
  !DD $095BF4A82, $0E2B87A14, $07BB12BAE, $00CB61B38
  !DD $092D28E9B, $0E5D5BE0D, $07CDCEFB7, $00BDBDF21
  !DD $086D3D2D4, $0F1D4E242, $068DDB3F8, $01FDA836E
  !DD $081BE16CD, $0F6B9265B, $06FB077E1, $018B74777
  !DD $088085AE6, $0FF0F6A70, $066063BCA, $011010B5C
  !DD $08F659EFF, $0F862AE69, $0616BFFD3, $0166CCF45
  !DD $0A00AE278, $0D70DD2EE, $04E048354, $03903B3C2
  !DD $0A7672661, $0D06016F7, $04969474D, $03E6E77DB
  !DD $0AED16A4A, $0D9D65ADC, $040DF0B66, $037D83BF0
  !DD $0A9BCAE53, $0DEBB9EC5, $047B2CF7F, $030B5FFE9
  !DD $0BDBDF21C, $0CABAC28A, $053B39330, $024B4A3A6
  !DD $0BAD03605, $0CDD70693, $054DE5729, $023D967BF
  !DD $0B3667A2E, $0C4614AB8, $05D681B02, $02A6F2B94
  !DD $0B40BBE37, $0C30C8EA1, $05A05DF1B, $02D02EF8D
  !EndTable:
  EndDataSection ;}/
EndProcedure

;{/ Adler32: Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43378
;/ Adler32 - an algorithm used by ZIP files that creates a 32-bit CheckSum.
;/ The algorithm is approximately 33% faster than CRC32, And nearly As reliable.
;/ Adler32 is a 32-bit extension And improvement of The Fletcher algorithm,
;}/ used in The ITU-T x.224 / ISO 8073 standard.
Procedure.l Adler32(Buffer.l, BufLen.l, Seed.l)
  !MOV Edx, dword [p.v_Seed]
  !MOVZX Ecx, dx
  !SHR Edx, 16
  !MOV Esi, dword [p.v_Buffer]
  !MOV Eax, dword [p.v_BufLen]
  !ADD Eax, Esi
  !XOR Ebx, Ebx
  !_alder321:
  !MOV bl, [Esi]
  !ADD Ecx, Ebx
  !CMP Ecx, 65521
  !JB near _alder322
  !SUB Ecx, 65521
  !_alder322:
  !ADD Edx, Ecx
  !CMP Edx, 65521
  !JB near _alder323
  !SUB Edx, 65521
  !_alder323:
  !INC Esi
  !CMP Esi, Eax
  !JNZ near _alder321
  !SHL Edx, 16
  !ADD Ecx, Edx
  !MOV Eax, Ecx
  ProcedureReturn
EndProcedure

;{/ FNV32 Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43379
;/ FNV32 - A very simple algorithm designed for high-speed
;/ hashing resulting in highly dispersed hashes With minimal collisions. 
;}/ Named after its creators Glenn Fowler, Phong Vo, And Landon Curt Noll. 
Procedure.l FNV32(Buffer.l, BufLen.l, OffsetBasis.l)
  !MOV Esi, dword [p.v_Buffer]      ;esi = ptr to buffer
  !MOV Ecx, dword [p.v_BufLen]      ;ecx = length of buffer (counter)
  !MOV Eax, dword [p.v_OffsetBasis] ;set to 0 for FNV-0, or 2166136261 for FNV-1
  !MOV Edi, 0x01000193              ;FNV_32_PRIME = 16777619
  !XOR Ebx, Ebx                     ;ebx = 0
  !_fnv321:
  !MUL Edi                          ;eax = eax * FNV_32_PRIME
  !MOV bl, [Esi]                    ;bl = byte from esi
  !XOR Eax, Ebx                     ;al = al xor bl
  !INC Esi                          ;esi = esi + 1 (buffer pos)
  !DEC Ecx                          ;ecx = ecx - 1 (counter)
  !JNZ near _fnv321                 ;if ecx is 0, jmp to _fnv321
  ProcedureReturn
EndProcedure
 
;{/ ELF32: Wayne Diamond, 2004-01-01 / PB4: sverson, 2006-08-14
;/ http://www.purebasic.fr/english/viewtopic.php?p=43381
;/ ELF32 - Outputs a 32-bit unsigned hash that is the modulo
;/ generated by dividing the returned integer by the Size of the table.
;}/ Used in UNIX object files that use the ELF format. 
Procedure.l ELF32(Buffer.l, BufLen.l)
  !XOR Ebx, Ebx                ; ebx = result holder (H)
  !MOV Edx, dword [p.v_BufLen] ; edx = Length
  !MOV Ecx, dword [p.v_Buffer] ; ecx = Ptr to string
  !XOR Esi, Esi                ; esi = temp holder
  !_elf321:
  !XOR Eax, Eax
  !SHL Ebx, 4
  !MOV al, [Ecx]
  !ADD Ebx, Eax
  !INC Ecx
  !MOV Eax, Ebx
  !AND Eax, 0xF0000000
  !CMP Eax, 0
  !JE near _elf322
  !MOV Esi, Eax
  !SHR Esi, 24
  !XOR Ebx, Esi
  !_elf322:
  !NOT Eax
  !AND Ebx,Eax
  !DEC Edx
  !CMP Edx, 0
  !JNE near _elf321
  !MOV Eax, Ebx
  ProcedureReturn
EndProcedure

;// MAIN

TestFile.s   = #PB_Compiler_Home+"Compilers\PBCompiler.exe"
Info.s      = TestFile+Chr(10)+Chr(10)
Loops.l     = 3 

If ReadFile(0,TestFile)
  BufferLen.l = Lof(0)
  *Buffer = AllocateMemory(BufferLen)
  If *Buffer
    QueryPerformanceCounter_(@QPC0a.q)
    If ReadData(0,*Buffer,BufferLen) = BufferLen
      QueryPerformanceCounter_(@QPC0b.q)
      
      QueryPerformanceFrequency_(@QPF.q)

      Info + "LoadFile:"+Chr(9)+Chr(9)+StrF(((QPC0b-QPC0a)/QPF)*1000)+" ms"+Chr(10)+Chr(10)
      
      While Loops
        QueryPerformanceCounter_(@QPC1.q)
        CRC32dCheckSum.l   = CRC32d(*Buffer, BufferLen)
        QueryPerformanceCounter_(@QPC2.q)
        CRC32eCheckSum.l  = CRC32e(*Buffer, BufferLen)
        QueryPerformanceCounter_(@QPC3.q)
        CRC32Fingerprint.l= CRC32Fingerprint(*Buffer, BufferLen)
        QueryPerformanceCounter_(@QPC4.q)
        Adler32CheckSum.l = Adler32(*Buffer, BufferLen, 1)
        QueryPerformanceCounter_(@QPC5.q)
        FNV32CheckSum.l   = FNV32(*Buffer, BufferLen, 0)
        QueryPerformanceCounter_(@QPC6.q)
        ELF32CheckSum.l   = ELF32(*Buffer, BufferLen)
        QueryPerformanceCounter_(@QPC7.q)
        Info + "CRC32 Diamond:"+Chr(9)+RSet(Hex(CRC32dCheckSum),8,"0")+Chr(9)+StrF(((QPC2-QPC1)/QPF)*1000)+" ms"+Chr(10)
        Info + "CRC32 El_Choni:"+Chr(9)+RSet(Hex(CRC32eCheckSum),8,"0")+Chr(9)+StrF(((QPC3-QPC2)/QPF)*1000)+" ms"+Chr(10)
        Info + "CRC32 PureBasic:"+Chr(9)+RSet(Hex(CRC32Fingerprint),8,"0")+Chr(9)+StrF(((QPC4-QPC3)/QPF)*1000)+" ms"+Chr(10)
        Info + "Adler32 Diamond:"+Chr(9)+RSet(Hex(Adler32CheckSum),8,"0")+Chr(9)+StrF(((QPC5-QPC4)/QPF)*1000)+" ms"+Chr(10)
        Info + "FNV32 Diamond:"+Chr(9)+RSet(Hex(FNV32CheckSum),8,"0")+Chr(9)+StrF(((QPC6-QPC5)/QPF)*1000)+" ms"+Chr(10)
        Info + "ELF32 Diamond:"+Chr(9)+RSet(Hex(ELF32CheckSum),8,"0")+Chr(9)+StrF(((QPC7-QPC6)/QPF)*1000)+" ms"+Chr(10)
        Info + Chr(10)
        Loops -1
      Wend
      
      MessageRequester("Checksum",Info)
      
    EndIf
  EndIf
  CloseFile(0)
EndIf

End
PB is great! :!: :)

;-) sverson
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

nice, should be in tricks and tips.
can be useful, one day.
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Post Reply