unsigned 32 bit arithmetic type?

sturlamolden sturlamolden at yahoo.no
Wed Oct 25 19:22:10 CEST 2006


Robin Becker wrote:
>
> > ULONG CalcTableChecksum(ULONG *Table, ULONG Length)
> > {
> > ULONG Sum = 0L;
> > ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG);
> >
> > while (Table < EndPtr)
> > 	Sum += *Table++;
> > return Sum;
> > }

Is this what you want?

import numpy
def CalcTableChecksum(Table, Length=None):
   tmp = numpy.array(Table,dtype=numpy.uint32)
   if Length == None: Length = tmp.size
   endptr = ((Length+3) & ~3) / 4
   return (tmp[0:endptr]).sum()





as nx
type(nx.array([1,2,3],dtype=nx.uint32)[0])



> so effectively we're doing only additions and letting bits roll off the end.
>
> Of course the actual semantics is dependent on what C unsigned arithmetic does
> so we're relying on that being the same everywhere.
>
> This algorithm was pretty simple in Python until 2.3 when shifts over the end of
> ints started going wrong. For some reason we didn't do the obvious and just do
> everything in longs and just mask off the upper bits. For some reason (probably
> my fault) we seem to have accumulated code like
>
> def _L2U32(L):
>      '''convert a long to u32'''
>      return unpack('l',pack('L',L))[0]
>
>
> if sys.hexversion>=0x02030000:
>          def add32(x, y):
>              "Calculate (x + y) modulo 2**32"
>              return _L2U32((long(x)+y) & 0xffffffffL)
> else:
>          def add32(x, y):
>              "Calculate (x + y) modulo 2**32"
>              lo = (x & 0xFFFF) + (y & 0xFFFF)
>              hi = (x >> 16) + (y >> 16) + (lo >> 16)
>              return (hi << 16) | (lo & 0xFFFF)
>
> def calcChecksum(data):
>          """Calculates TTF-style checksums"""
>          if len(data)&3: data = data + (4-(len(data)&3))*"\0"
>          sum = 0
>          for n in unpack(">%dl" % (len(data)>>2), data):
>              sum = add32(sum,n)
>          return sum
>
> and also silly stuff like
>
> def testAdd32(self):
>      "Test add32"
>      self.assertEquals(add32(10, -6), 4)
>      self.assertEquals(add32(6, -10), -4)
>      self.assertEquals(add32(_L2U32(0x80000000L), -1), 0x7FFFFFFF)
>      self.assertEquals(add32(0x7FFFFFFF, 1), _L2U32(0x80000000L))
>
> def testChecksum(self):
>      "Test calcChecksum function"
>      self.assertEquals(calcChecksum(""), 0)
>      self.assertEquals(calcChecksum("\1"), 0x01000000)
>      self.assertEquals(calcChecksum("\x01\x02\x03\x04\x10\x20\x30\x40"), 0x11223344)
>      self.assertEquals(calcChecksum("\x81"), _L2U32(0x81000000L))
>    _L2U32(0x80000000L))
>
> where while it might be reasonable to do testing it seems the tests aren't very
> sensible eg what is -6 doing in a u32 test? This stuff just about works on a 32
> bit machine, but is failing miserably on a 64bit AMD. As far as I can see I just
> need to use masked longs throughout.
>
> In a C extension I can still do the computation exfficiently on a 32bit machine,
> but I need to do masking for a 64 bit machine.
> -- 
> Robin Becker




More information about the Python-list mailing list