Thread: Bit Shift in a Byte

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    106

    Bit Shift in a Byte

    Hi Guys,
    I want to shift a byte from the left and right so that it becomes more condensed in the middle for each iteration.
    also shifting zeros in either direction so the original value will always be destroyed after a maximum of four iterations.

    The best I can think of is using logical operation to split the byte into
    a pair of four bit nibbles, shift each of them in either direction,
    and then another operation to superimpose them back to a byte.

    This seems a lot of time.. Is there a better way?
    Cheers, Art.

    Code:
    INPUT:   b10101010
    OUTPUT:  b01010100
    
    
    INPUT:   b11100111
    OUTPUT1: b01111110
    OUTPUT2: b00111100
    OUTPUT3: b00011000
    OUTPUT4: b00000000

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by xArt
    The best I can think of is using logical operation to split the byte into
    a pair of four bit nibbles, shift each of them in either direction,
    and then another operation to superimpose them back to a byte.

    This seems a lot of time.. Is there a better way?
    It seems like five bitwise operations to me, but I could be mistaken:
    Code:
    x = ((x >> 1) & 0xf0) | ((x << 1) & 0x0f); /* assuming 8-bit bytes */
    Have you tested and found that such an approach really is too slow for your requirements? If so, then given that there are 256 possible values, perhaps you could try with a lookup table.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jan 2013
    Posts
    106
    Hi, that is similar approach that I have so far.
    No I’m not complaining it’s too slow yet, just checking I’m not doing anything stupid
    There will be a lot of these operations.

    Here is a problem though.. .what if it were only five bits?
    There I am stuck at the moment because there is a middle bit.

    EDIT,,, I think I have it... just leave the middle bit alone when separating the nibbles.

    Code:
        unsigned char bitbyte = 0b11110101;
        unsigned char opabyte = 0;
        unsigned char opbbyte = 0;
        unsigned char outbyte = 0;
    
    
        if (cntone == 0) {
    
    
            bitbyte = bitbyte & 0x1F; // clear most significant three bits
    
            //
    
            opabyte = bitbyte & 0x0F; // seperate nibble pairs
            opbbyte = bitbyte & 0xF0; //
    
            opabyte = opabyte << 1; // shift nibbles left and right
            opbbyte = opbbyte >> 1; //
    
            outbyte = opabyte | opbbyte; // superimpose nibbles to new byte
    
    
            NSLog(@":%02x ",opabyte); // working nibble values
            NSLog(@":%02x ",opbbyte); //
    
            NSLog(@":%02x ",outbyte); // result byte value
    
            cntone = 1; // send to log only once
    
        }
    Last edited by xArt; 05-31-2015 at 01:14 AM.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by xArt
    Here is a problem though.. .what if it were only five bits?
    There I am stuck at the moment because there is a middle bit.

    EDIT,,, I think I have it... just leave the middle bit alone when separating the nibbles.
    I am a little confused though: your solution is essentially the same as mine, which is an implementation of what you described for an 8-bit byte, i.e., you are not treating the case of 5 bits any different from 8 bits, except that coincidentally three of the bits are always zero.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Jan 2013
    Posts
    106
    Hi, yes sorry I didn’t explain well, that was just my eight bit example to show I was essentially doing the same thing,
    and the clearing of the first three bits was thrown in there when I realised I’m dealing with five bits instead of eight.

    I aim to rotate 5x7 monocrome text vertically so that when done to a whole line,
    it’s supposed to appear like a demo effect where the old characters individually spin around their vertical axis
    and the new character is revealed as if the new character was behind the old character the whole time.

    It might get more complicated though.. I’m not sure that just compressing them horizontally and restoring them
    will look like spinning at all. It might also require the character is tilted also (which will be a pain in the bum).

    Code:
     xxx   xxxx    xxx
    x   x  x   x  x   x
    x   x  x   x  x
    xxxxx  xxxx   x
    x   x  x   x  x
    x   x  x   x  x   x
    x   x  xxxx    xxx
    Two steps of squashing them would be this.. and I’m not sure it will be so simple...

    Code:
     x   xx    x
    x x  x x  x x
    x x  x x  x
    xxx  xx   x
    x x  x x  x
    x x  x x  x x
    x x  xx    x
    Last edited by xArt; 06-01-2015 at 12:41 AM.

  6. #6
    Registered User
    Join Date
    Jan 2013
    Posts
    106
    Hi again
    So I haven’t had much programming time, but recently finished that step handling five bits.
    I went for... if the bit either side of the centre bit was set, the new middle bit will be set in the output byte.

    The next question I would like to ask is, say I have an array of “bitbyte[s]”, how do I bitwise rotate the LS bit
    of each byte in the array? like a two dimensional array that would be easy if it was done with bigger variable types.

    The best I can think of is iterate the array, checking with & ,then writing the next bit with | in sequence,
    essentially doing a similar thing as the first step?

    Code:
        unsigned char bitbyte = 0b11111011;
        unsigned char opabyte = 0;
        unsigned char opbbyte = 0;
        unsigned char outbyte = 0;
    unsignedchar midbyte = 0; // buffer to store middle bit
    
    
        if (cntone == 0) {
    
            bitbyte = bitbyte & 0x1F; // clear most significant three bits
    
            opabyte = bitbyte & 0x03; // seperate nibble pairs
            opbbyte = bitbyte & 0x18; // leaving middle bit alone
            midbyte = bitbyte & 0x0A; // store bits surrounding middle bit
    
            NSLog(@":%02x ",opabyte); // working nibble values
            NSLog(@":%02x ",opbbyte); //
    
            opabyte = opabyte << 1; // shift nibbles left and right
            opbbyte = opbbyte >> 1; //
    
            outbyte = opabyte | opbbyte; // superimpose nibbles to new byte
    
            if (midbyte != 0) { // correct the middle bit
            outbyte = outbyte | 0x04; // set middle bit
            } else { // cycle time balance
            bitbyte = bitbyte | 0x04; // don't need the input value anymore
            } // midbyte
    
            NSLog(@":%02x ",opabyte); // working nibble values
            NSLog(@":%02x ",opbbyte); //
    
            NSLog(@":%02x ",outbyte); // result byte value
    
            NSLog(@"    "); // spacer
    
    if (cntone < 1) { // not needed for cyclic implementation
            cntone++; // calculate and send to log only once
            }
        }
    
    next step I’m asking about:

    Code:
      x x    x x    x x
     x  x  xx  x   x  
    x  xx  x  x   x
    x x x  x x x  x
    xx  x  xx  x  x   x
    x      x  x   x  x 
    x      x      x
    Last edited by xArt; 06-03-2015 at 01:45 AM.

  7. #7
    Registered User
    Join Date
    May 2015
    Posts
    65
    I honestly cannot figure out what you want to do, which is a shame, as I like these kinds of challenges.

    Anyway, playing around with structs, unions and bitfields (if nothing else for the fun of it) comes to mind.

    Code:
    typedef union Type_ {
        struct {
            uint8_t right:4;
            uint8_t left:4;
        } Fields;
        uint_8 byte;
    } Type;
    Dunno if this is even remotely down the right alley, or if it will work at all, just thought I'd throw it in there.

  8. #8
    Registered User
    Join Date
    Jan 2013
    Posts
    106
    You have to click the “To Plain Text” button for the images in code to align properly.
    The code so far is to compress a single line of the char graphics which are all five bit wide, but obviously still stored in bytes.

    For an entire character graphic, 7 bytes are needed, and to tilt them, the bitwise shift will have to occur
    vertically rather than horizontal across one byte.

    I have verified that just squashing a character and expanding it again does not look like spinning.
    It would have to be tilted as well.

  9. #9
    Registered User
    Join Date
    Jan 2013
    Posts
    106
    This would make more sense (last part of the video).
    I don’t think I have to tilt the characters for the effect I want.

    https://www.youtube.com/watch?v=bN-XRXLx88Y

  10. #10
    Registered User
    Join Date
    May 2015
    Posts
    65
    Ah, know I think I know what you mean.

    This:
    Code:
    union
    {    struct
        {
            uint8_t a:4, b:4;
        } bitFields;
        uint8_t c;
    } myStruct;
        
    myStruct.c = 0xff;
    printf("%d\n", myStruct.c);
    myStruct.bitFields.a <<= 1;
    myStruct.bitFields.b >>= 1;
    Surprisingly works on my system, but I haven't the slightest clue how portable and safe it is. Also, you will of course be aware that there's no way of expanding said byte again.

    At any rate, it is interesting and I'm sure I'll get some fun out of it.

  11. #11
    Registered User
    Join Date
    May 2015
    Posts
    65
    Or what about this overly complicated one liner, complete with error checking?
    The first value is the byte you wish to rotate, and the second is by how much. if 'i' is 0, you it will return the value with no changes, if 4, it will return 0, and if above 7 will also return 0, as an error. It's not much of an error, but we have to return something.

    Code:
    inline uint8_t rotate( uint8_t b, unsigned int i )
    {
        return (i < 8) ? ( ( ( b << ( ( i <= 4 ) ? ( i ) : ( 8 -i ) ) ) & 0xf ) | ( ( b >> ( ( i <= 4 ) ? ( i ) : ( 8 - i ) ) ) & 0xf0 ) ) : ( 0 );
    }
    Edit:

    or to go completely overboard:

    Code:
    typedef uint8_t rotate_type;
    inline rotate_type rotate( rotate_type b, unsigned int i )
    {
        return (i < ( sizeof( rotate_type ) * 8 )) ? ( ( ( b << ( ( i <= ( sizeof( rotate_type ) *4 ) ) ? ( i ) : ( ( sizeof( rotate_type ) * 8 ) - i ) ) ) & 0xf ) | ( ( b >> ( ( i <= ( sizeof( rotate_type ) * 4 ) ) ? ( i ) : ( ( sizeof( rotate_type ) * 8 ) - i ) ) ) & 0xf0 ) ) : ( 0 );
    }

    Best of luck figuring it out.
    Last edited by Zacariaz; 06-12-2015 at 04:08 PM.

  12. #12
    Registered User
    Join Date
    May 2015
    Posts
    65
    Last one, I promise...

    Code:
    #include <stdint.h>
    #define R_T uint8_t
    #define R_WIDTH ( sizeof ( R_T ) * 8 )
    
    
    inline R_T rotate( R_T b, unsigned int i )
    {
        return ( ( ( R_T ) -1 >> ( R_WIDTH / 2 ) ) & ( b << ( ( ( i % R_WIDTH ) <= ( R_WIDTH / 2 ) ) ? ( i % R_WIDTH ) : ( R_WIDTH - ( i % R_WIDTH ) ) ) ) ) | ( ( ( R_T ) -1 << ( R_WIDTH / 2 ) ) & ( b >> ( ( ( i % R_WIDTH ) <= ( R_WIDTH / 2 ) ) ? ( i % R_WIDTH ) : ( R_WIDTH - ( i % R_WIDTH ) ) ) ) );
    }
    Now I'm bored...

  13. #13
    Registered User
    Join Date
    Jan 2013
    Posts
    106
    Lol but I already did the thing
    The next step would be tilting any vertical line of a complete character, but I dont think its needed.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Shift Left, Shift Right Question
    By congi in forum C Programming
    Replies: 1
    Last Post: 01-28-2015, 10:45 AM
  2. Replies: 11
    Last Post: 05-19-2013, 04:16 PM
  3. logical shift and arithmetic shift.(bit shifting in C )
    By A34Chris in forum C Programming
    Replies: 20
    Last Post: 09-03-2012, 11:22 AM
  4. reading files byte by byte
    By cpsc in forum C++ Programming
    Replies: 12
    Last Post: 01-07-2011, 03:54 PM
  5. how can I shift bit right a byte array
    By lovesunset21 in forum C Programming
    Replies: 10
    Last Post: 11-03-2010, 02:31 PM