Python update trouble (2.3 to 2.4): x<<y
Gonzalo Monzón
gmc at serveisw3.net
Sun May 21 15:22:32 EDT 2006
Thank you for all the suggestions! :-)
The C routine is almost -changing data type long for word- a copy of the
function given by a hardware manufacturer, the same code used in their
firmware to calc the checksum of every piece of data sent or received,
and that data is somewhat special: it does not contain only plain ascii
character data (only 0x01 - 0x09 as delimiters) and every data set ends
with a 0x00 null byte so its fine to calculating checksum until "\x00"
is reached. And I must get the same crc calculations. That C routine
(and a very similar PHP one too) are tested for months and work smoothly.
And of course I should use integer not long!!... we aren't anymore in
the 8 bit computer era... ;-) original code from hardware manufacturer
use words by the way. And now really don't know why I used long. I
thought I did that way 'cause see pyrex C generated glue code always
using PyInt_FromLong so thought would use the same type.
I changed the C function to use integer, and it is performing a little
bit slowly than using longs (best with long: 0.614us, best with int:
0.629us), that is maybe as I said due pyrex glueing always the return
values with PyObject* PyInt_FromLong for all kind of short int to long
data types? Anyway both results are fine, and the timming gap is
insignificant (int: 1580403 loops -> 0.973 secs, long: 1601902 loops ->
1.01 secs) as i usually never have to call more than 100,000 times when
loading a full file data backup.
As a note for the checksum algorithm used here, I thought the hardware
manufacturer implemented this some years ago for serial data
transmission, but later attached some ethernet ports and they wanted to
have the protocol compatible. Anyway as I see in the link you reply, it
seems to be based in CCITT CRC-16, but they adapted to their own
requirements -performace issues for the hardware unit?- (never 0x00, etc.)
Regards,
Gonzalo.
John Machin escribió:
>Gonzalo wrote:
>"""
>I missed the point to add the *and* to workaround the long result
>issue!
>I think I understand it now.
>
>I am timing the code once translated, so here are the results for the
>crc calculation function.
>"""
>
>Yes, and both of us were missing the point that the "16" means 16 bits
>wide!! It is carrying an extra 16 redundant bits that don't contribute
>to the checking ability.
>
>If your software *needs* to generate/check the exact same 32-bit-wide
>CRC as calculated by that C routine, then what I gave you should be OK.
> Do you have any more test values? In particular test an empty string
>and say "\x00" * 8 -- sometimes a CRC specification will do something
>special with short strings e.g. pad them put with null bytes.
>
>That C routine is actually, on further reading, mind-boggling!! It
>stops on a null byte, rather than working on a given length. A CRC is
>normally expected to work on any data (including binary data) whether
>it contains \x00 or not. What are you using it for??
>
>If you don't have to interface with other software, AND a 16-bit check
>is adequate, then at the end of this message is a 16-bit version which
>will use only ints and therefore may run faster.
>
>However you may wish to use a CRC32 which is supplied with Python (in
>the binascii module).
>
>A further note: what we have so far seems not to be the CCITT aka X.25
>standard CRC-16 , but a reflection. See
>http://www.joegeluso.com/software/articles/ccitt.htm
>and also if you have the time and the determination, the article by
>Ross Williams that it refers to.
>
>Cheers,
>John
>
>=== 16-bit version ===
>gCRC16Table = []
>
>def InitCRC16():
> global gCRC16Table
> for i in xrange(0,256):
> crc = i << 8
> for j in xrange(0,8):
> if (crc & 0x8000) != 0:
> tmp = 0x1021
> else:
> tmp = 0
> crc = (crc << 1) ^ tmp
> crc &= 0xFFFF
> gCRC16Table.append(crc)
>
>def CalcCRC16(astr):
> crc = 0xFFFF
> for c in astr:
> crc = gCRC16Table[((crc >> 8) & 255)] ^ ((crc & 0xFF) << 8) ^
>ord(c)
> assert 0 <= crc <= 0xffff # remove when doing timings :-)
> return crc
>
>test = "123456asdfg12345123"
>InitCRC16()
>result = CalcCRC16(test)
>print result, hex(result)
>======
>
>
>
More information about the Python-list
mailing list