2

my solution

get the rightmost n bits of y
a = ~(~0 << n) & y

clean the n bits of x beginning from p
c = ( ~0 << p | ~(~0 << (p-n+1))) & x

set the cleaned n bits to the n rightmost bits of y
c | (a << (p-n+1))

it is rather long statements. do we have a better one?

 i.e
x = 0 1 1 1 0 1 1 0 1 1 1 0
p = 4
y = 0 1 0 1 1 0 1 0 1 0 
n = 3

the 3 rightmost bits of y is 0 1 0 
it will replace x from bits 4 to bits 2 which is 1 1 1
SecureFish
  • 2,391
  • 7
  • 32
  • 43
  • 1
    the "n bits that begin at position p" go from `p` to `p+n-1`... So why does `p-n+1` show up in your expression (twice)? – Nemo Jul 18 '11 at 00:54
  • the whole manipulation includes two parts, I am talking about beginning from rightmost parts: bits [p-n+1,p], and bits [0,p-n+1]. We want to change the value of the firs part and keep the second part unchanged. – SecureFish Jul 18 '11 at 01:12
  • Right, but the bits from [p-n+1,p] are the n bits _ending_ at position p, not the n bits _starting_ at position p as your question says. (Assuming bits "start" from 0...) I think you need to fix your code or fix your question... – Nemo Jul 18 '11 at 01:16
  • begins from p assuming iterate the bits string from left to right. Yes, you are right, I should have made it clearer. – SecureFish Jul 18 '11 at 01:30
  • Yeah, I would phrase it just like you did in your comment: "From bit p-n+1 to bit p." If you say a bit string "begins at bit 7 and ends at bit 5" I bet 50% of programmers would take issue with that phrasing :-) – Nemo Jul 18 '11 at 01:32
  • Read my answer here: [**To Set all bits One from n to m**](http://stackoverflow.com/questions/15917454/set-the-m-bit-to-n-bit/15918195#15918195) – Grijesh Chauhan Jul 14 '13 at 21:05

3 Answers3

1

I wrote similar one:

 unsigned setbits (unsigned x, int p, int n, unsigned y)
{
  return (x & ~(~(~0<<n)<<(p+1-n)))|((y & ~(~0<<n))<<(p+1-n));
}
arlekin
  • 11
  • 1
0

Have a look at the following descriptive code:

int setbitsKR(int x, int p, int n, int y){
    int shiftingDistance = p - n + 1,
        bitmask = (1 << n) - 1, // example, 11
        digitsOfY = (y & bitmask) << shiftingDistance, // whatever        
        bitmaskShiftedToLeft = bitmask << shiftingDistance, // 001100
        invertedBitmaskShiftedToLeft = ~bitmaskShiftedToLeft; // 110011

    // erase those middle bits of x
    x &= invertedBitmaskShiftedToLeft;

    // add those bits from y into x
    x |= digitsOfY;

    return x;
}

In short, it creates a bitmask (string of 1s), shifts them to get to that middle position of x, nukes those bits of x by &ing with a string of 0s (inverted bitmask), and finally |s that position with the right digits of y.

Gaurang Tandon
  • 6,504
  • 11
  • 47
  • 84
0

There are two reasonable approaches.

One is yours: Grab the low n bits of y, nuke the middle n bits of x, and "or" them into place.

The other is to build the answer from three parts: Low bits "or" middle bits "or" high bits.

I think I actually like your version better, because I bet n and p are more likely to be compile-time constants than x and y. So your answer becomes two masking operations with constants and one "or"; I doubt you will do better.

I might modify it slightly to make it easier to read:

mask = (~0 << p | ~(~0 << (p-n+1)))
result = (mask & a) | (~mask & (y << (p-n+1)))

...but this is the same speed (indeed, code) as yours when mask is a constant, and quite possibly slower when mask is a variable.

Finally, make sure you have a good reason to worry about this in the first place. Clean code is good, but for something this short, put it in a well-documented function and it does not matter that much. Fast code is good, but do not attempt to micro-optimize something like this until your profiler tells you do. (Modern CPUs do this stuff very fast; it is unlikely your application's performance is bounded by this sort of function. At the very least it is "innocent until proven guilty".)

Nemo
  • 70,042
  • 10
  • 116
  • 153