Dimo
Dimo

Reputation: 51

C function to Python (different results)

I am trying to port this snippet of code to python from C. The outputs are different even though it's the same code.

This is the C version of the code which works:

int main(void)
{

uint8_t pac[] = {0x033,0x55,0x22,0x65,0x76};
uint8_t len = 5;
uint8_t chan = 0x64;

btLeWhiten(pac, len, chan);

    for(int i = 0;i<=len;i++)
    {
        printf("Whiten %02d \r\n",pac[i]);
     }

   while(1)
   {    

   }

  return 0;
  }



void btLeWhiten(uint8_t* data, uint8_t len, uint8_t whitenCoeff)
{

uint8_t  m;

while(len--){   
    for(m = 1; m; m <<= 1){

        if(whitenCoeff & 0x80){

            whitenCoeff ^= 0x11;
            (*data) ^= m;
        }
        whitenCoeff <<= 1;

    }
    data++;
  }
}

What I currently have in Python is:

def whiten(data, len, whitenCoeff):
    idx = len 
    while(idx > 0):
        m = 0x01
        for i in range(0,8):
            if(whitenCoeff & 0x80):
                whitenCoeff ^= 0x11
                data[len - idx -1 ] ^= m
                whitenCoeff <<= 1 
                m  <<= 0x01

        idx = idx - 1


pac = [0x33,0x55,0x22,0x65,0x76]
len = 5
chan = 0x64

def main():

whiten(pac,5,chan)
print pac


if __name__=="__main__":
    main()

The problem i see is that whitenCoeff always remain 8 bits in the C snippet but it gets larger than 8 bits in Python on each loop pass.

Upvotes: 3

Views: 106

Answers (5)

Noctis Skytower
Noctis Skytower

Reputation: 22031

Your code in C does not appear to work as intended since it displays one more value than is available in pac. Correcting for this should cause 5 values to be displayed instead of 6 values. To copy the logic from C over to Python, the following was written in an attempt to duplicate the results:

#! /usr/bin/env python3
def main():
    pac = bytearray(b'\x33\x55\x22\x65\x76')
    chan = 0x64
    bt_le_whiten(pac, chan)
    print('\n'.join(map('Whiten {:02}'.format, pac)))


def bt_le_whiten(data, whiten_coeff):
    for offset in range(len(data)):
        m = 1
        while m & 0xFF:
            if whiten_coeff & 0x80:
                whiten_coeff ^= 0x11
                data[offset] ^= m
            whiten_coeff <<= 1
            whiten_coeff &= 0xFF
            m <<= 1


if __name__ == '__main__':
    main()

To simulate 8-bit unsigned integers, the snippet & 0xFF is used in several places to truncate numbers to the proper size. The bytearray data type is used to store pac since that appears to be the most appropriate storage method in this case. The code still needs documentation to properly understand it.

Upvotes: 0

Dimo
Dimo

Reputation: 51

I solved it by anding the python code with 0xFF. That keeps the variable from increasing beyond 8 bits.

Upvotes: 0

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140216

whitenCoeff <<= 1 in C becomes 0 after a while because it is a 8-bit data.

In python, there's no such limit, so you have to write:

whitenCoeff = (whitenCoeff<<1) & 0xFF

to mask higher bits out.

(don't forget to check vz0 remark on array boundary)

plus there was an indentation issue.

rewritten code which gives same result:

def whiten(data, whitenCoeff):
    idx = len(data)
    while(idx > 0):
        m = 0x01
        for i in range(0,8):
            if(whitenCoeff & 0x80):
                whitenCoeff ^= 0x11
                data[-idx] ^= m
            whitenCoeff = (whitenCoeff<<1) & 0xFF
            m  <<= 0x01

        idx = idx - 1


pac = [0x33,0x55,0x22,0x65,0x76]
chan = 0x64

def main():

    whiten(pac,chan)
    print(pac)


if __name__=="__main__":
    main()

Slightly off-topic: Note that the C version already has problems:

for(int i = 0;i<=len;i++)

should be

for(int i = 0;i<len;i++)

Upvotes: 1

vz0
vz0

Reputation: 32923

In C you are writing data from 0 to len-1 but in Python you are writing data from -1 to len-2. Remove the -1 from this line:

data[len - idx -1 ] ^= m

like this

data[len - idx] ^= m

you also need to put this line outside the if:

whitenCoeff <<= 1 

Upvotes: 1

Blender
Blender

Reputation: 298326

You've got a few more problems.

  1. whitenCoeff <<= 1; is outside of the if block in your C code, but it's inside of the if block in your Python code.
  2. data[len - idx -1 ] ^= m wasn't translated correctly, it works backwards from the C code.

This code produces the same output as your C code:

def whiten(data, whitenCoeff):
    for index in range(len(data)):
        for i in range(8):
            if (whitenCoeff & 0x80):
                whitenCoeff ^= 0x11
                data[index] ^= (1 << i)

            whitenCoeff = (whitenCoeff << 1) & 0xff

    return data

if __name__=="__main__":
    print whiten([0x33,0x55,0x22,0x65,0x76], 0x64)

Upvotes: 1

Related Questions