Go Down

Topic: Bitshifting bytes to form a long var fails! (Read 4924 times) previous topic - next topic

dhenry

Quote
print_hex() is really slow on that! Something faster would be great!


The whole piece doesn't make a lot of sense to me, with all the left shifting + right shifting involved. If you can articulate what you are trying to do, people may be able to better help you.

Nick Gammon


I will try the mods from dhenry!


Oh yes? And what stopped you trying my suggestion in reply #15?

Quote
Code: [Select]
 address = long (a) << 16 | long (b) << 12 | c << 8 | d << 4 | e;


We are up to reply #43 and you act all surprised that a suggestion in reply #41 works. When (apart from the "unsigned" part) that was suggested in reply #15.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

psyche



I will try the mods from dhenry!


Oh yes? And what stopped you trying my suggestion in reply #15?

Quote
Code: [Select]
  address = long (a) << 16 | long (b) << 12 | c << 8 | d << 4 | e;


We are up to reply #43 and you act all surprised that a suggestion in reply #41 works. When (apart from the "unsigned" part) that was suggested in reply #15.


There is no reason for me to lie to anyone here! I tried your suggestion but it didn't work. I dont know the reason why, maybe it is the bitshifting parts or a bug in Arduino IDE. 99% of the errors are made from humans,  i wrote some code which may had some mistakes BUT Arduino IDE is made by humans also! I didn't blame anyone and yes i was surprised that it did work! I don't know exactly who acts weird here but it is not me! I tried all the suggestions and two of them work! I don't want to offend anyone and i dont intend too!
Who knows, maybe it was a combination of mistakes that i did, which led to a non working code when you replied! I really can't know!
What i know is that when dhenry suggested me to change a few things, the code worked, thats all! If someone has a problem with dhenry's replies or anyone else's replies, itsnot me and i dont care who does! What i care is that i came here asking for help and i got it! I know who helped me and who didn't. The rest is history alreay!

Keep up the good work guys
Thank you for your help!

pYro_65

Quote
Who knows, maybe it was a combination of mistakes that i did

@psyche good to see you have it working, the previous examples were vaild.

And just to be picky:

If you want to reconstitute a long type from char types, here is something that you can try beyond all the shifting / union.
Code: [Select]


unsigned char *uc_ptr; //unsigned char ptr, used for conversion
...
 uc_ptr = (unsigned char *) &address; //point uc_ptr at the conversion results
 *uc_ptr++=dat1; //assign the 1st char
 *uc_ptr++=dat2; //assign the 2nd char
 *uc_ptr++=dat3; //assign the 3rd char
 *uc_ptr   =dat4; //assign the 4th char
 //after this point, address should contain the values represented by the four char types

Speed-wise, this will be as fast as the union approach and potentially faster. However, like the union approach, it is dependent on the compiler's endianess - so the code's portability is poor.


@dhnery, I hope there is more to come, most of your assumptions above are wrong. The task at hand is interlacing nibbles, more specifically 'un-serialisation' of data. The algorithm above is not intended for re-factoring and is almost guaranteed to be slower. One rule of thumb when designing an algorithm is assignments can be 'equal to' in speed compared to initialisations but never faster.

The algorithm above is typically used as  a replacement for a loop, or used in conjunction with one, to trade off size for greater speed.

Also on a side note, most compilers suffer a small side effect relating to using a 'pointer to' or 'reference of' constant data, as a result these constants cannot be considered 'compile time constants'.

As for comparing the above to my union in reply #30, just counting the operations shows it does less work before the compiler even gets to it.

Moving on to the versions in replies 1541, they are not quite as fast as the union due to their shifts greater than the native processor width, however they are faster than the above example too.
I haven't considered the union here as its use of bit fields is very inefficient.
And as for them being non-portable, there is no reason to not include endianess handling into the struct which would give you portablility.

Hope this gives some thoughts.
Cheers.

dhenry

Quote
The task at hand is interlacing nibbles, more specifically 'un-serialisation' of data.


To help you see it more explicitly:

Code: [Select]

#define n2uc(high_nibble, low_nibble)  (((high_nibble) & 0xf0) | ((low_nibble) & 0x0f))

...
  uc_ptr = (unsigned char *) &address;
  *uc_ptr++ = n2uc(d, e);
  *uc_ptr++ = n2uc(b, c);
  *uc_ptr   = n2uc(0, a);
  //done


You can find out which is faster.

pYro_65

#50
Oct 18, 2012, 04:07 am Last Edit: Oct 18, 2012, 04:31 am by pYro_65 Reason: 1
That won't do you justice.

For starters you don't write anything to the most significant byte. A variable declared on the stack will have an undefined contents until initialised or assigned. Therefore you read rubbish data off the stack.

Secondly you don't combine the data properly, you mask away the bits of 'high_nibble'

And no, apart from the fact the code is unusable, it is not faster.

This is probably what you intended.
Code: [Select]
 uc_ptr = (unsigned char *) &address;
 *uc_ptr++ = (( d << 4 ) | e);
 *uc_ptr++ = (( b << 4 ) | c);
 *uc_ptr++ = a;
 *uc_ptr = 0;


Which also is slower than a union construct.

Go Up