C#: Left Rotation Algorithm for different Bit Numbering Schemes - c#

So I have the following RotateLeft algorithm in C#:
public static ushort RotateLeft(ushort value, int count)
{
int left = value << count;
int right = value >> (16 - count);
return (ushort)(left | right);
}
Does this algorithm differ if the numbering scheme is different?
By numbering scheme I mean if it's MSB-0 or LSB-0
MSB-0
0 7
1 0 0 1 0 1 1 0
LSB-0
7 0
1 0 0 1 0 1 1 0
Say I wanted to shift left by 1, does having a different numbering scheme affect the algorithm?

It looks like that algorithm is agnostic of the underlying system's little- or big- endianness. That is to say, it will work the same regardless of the numbering scheme, since the OR operation adds the shifted bits back in on the other side before returning. Assuming you're using it for bit-level operations and flag checks, this might be all you need.
Without knowing how it fits into the rest of your program it's hard to say whether it will work the way you expect across different platforms using opposite bit numbering schemes. For example, if you run this on a device using MSB-0 and write some shifted data to a binary file, then read that binary data back in on a device using LSB-0, it probably won't be what you're expecting.
If your goal is to have your software work the same across differently-endian systems, take a look at the .NET BitConverter Class. If you're using this for efficient mathematical operations, the static BitConverter.IsLittleEndian field will let you check the underlying architecture so that you can shift the other way or reverse binary data accordingly.

Related

How to bit-shift a register to zero?

When you left-shift (<<) or right-shift (>>) an integer register, you pull in zeros from the opposite side. It stands to reason that if you shift by more than the width of a register (e.g. shift a uint by 32 or more bits), it should become all zeros. In C#, this is not what happens. Instead, the shift count is effectively interpreted mod the register width, so it is impossible to definitively make the register zero using shifts. This is a pain.
I got hit by this because I am representing an extra-large integer via a unit[]. When you perform bit shifts on the extra-large register, in general bits from different uint instances in the array must "mix", so the code does stuff like:
s[i] = (s[i+k] << n) | (s[i+k+1] >> (32 - n))
but this code fails when n = 0 or 32, i.e. when the shift corresponds to a pure shift among uint values with no mixing. (It's easy to write the code so that n = 32 never appears, but then the shift by (32 - n) still fails when n = 0.) For now, I have got around this problem by special-casing n = 0, but this is extra code (ugly) and an extra test-and-branch in a performance-critical spot (bad).
Can anyone suggest a modification (maybe using masking instead of or in addition to bit shifting?) to get around this difficulty? Can anyone explain why C# made the choice to make shift counts not behave according to naive expectations?

C# Get Label Address For Lookup Table?

I'm trying to optimize an algorithm I've been working on in C#. I have a while loop that will continue as long as a couple of variables are not 0. I was hoping to potentially replace this with some binary arithmetic & lookup table to avoid conditional branching.
while(a != 0 && b != 0 ) {
// DO WORK
}
I was hoping I might be able to do something like this:
var lookup_table = [next_iteration, done];
next_iteration:
// DO WORK
goto lookup_table[<< a&b? 0 : 1 >>];
done:
Replacing the << a&b? 0 : 1 >> with binary arithmetic. Probably folding all the bits to the 1s place in a & b, and then masking out other bits in the final AND operation. Perhaps there's a better technique.
Of course, this level of optimization may just be beyond the capabilities of C#/Managed Languages without dropping into IL (which could be a valid solution). In which case I can drop down to C/C++. I'm curious to see if I can't get it to work in C# though.

Jumping segments in binary

My question is, is there a way in C# with a starting bit location to find the next binary digit within a byte that has a specified value of 0 or 1 without iteration (looking for the highest performance option).
As an example, if you had 10011 and started at the first bit (far right) and searched for the first 0, it would be the 3rd place going right to left. If you then started at the 3rd place and wanted to find the next 1, it would be at the 5th place (far left).
Thanks for any help and feel free to let me know if I need to provide anything further.
Edit: Here is my current code.
private int GetBinarySegment(uint uiValue, int iStart, int iMaxBits, byte bValue)
{
int r = 0; uiValue >>= iStart;
if (uiValue == 0) return iMaxBits - iStart;
while ((uiValue & 1) == bValue) { uiValue >>= 1; r++; }
return r;
}
There are ways, but they're ugly because there's no _BitScanForward or equivalent intrinsic. Still, you can actually compute this thing efficiently without needing a huge table.
First step: make a number that has a 1 at the position you're searching for and 0 everywhere else.
If searching for a 1, that means x & -x. If searching for a 0, use ~x & (x + 1).
Then, use one of the many ways to emulate either bitscan (there is only one set bit now, so it doesn't matter which side you search from). Some ways to do that are detailed here (not in C#, but you can convert them).
Use a lookup table. That is, precalculate a 2D array indexed by byte value and current position. You can do a separate table for zeros and ones, or you can combine it.
So for your example, you start at bit 0 of the number 19. That happens to be a 1. So if you lookup nextBit[19][0] it should return 1, and so on. Here's what a combined lookup table might look like. It shows the next bit for both 0s and 1s:
nextBit[19][0] = 1 // 1
nextBit[19][1] = 4 // 1
nextBit[19][2] = 3 // 0
nextBit[19][3] = 4 // 0
nextBit[19][4] = 0 // 1
nextBit[19][5] = 6 // 0
nextBit[19][6] = 7 // 0
Obviously there is no 'next' for bit 7, and if 'next' returns 0, there are no more of that particular bit.
I may have interpreted your question incorrectly, but this technique can be modified to suit your purposes. I initially thought you wanted to navigate through all 1-bits or 0-bits. If instead you want to skip over consecutive 1-bits, then you just arrange your table in that way. Or indeed, you can have a 'next' for both 0 and 1 at each position.

Effectively storing bit indexes

I want to store certain indexes in a sequence of bits. The number of bits are powers of
two and it is safe to assume that maximum index to be 255 (starting index is 0). Earlier i was storing every index as an integer. But that occupies too much of memory.
I want to use something like masks.
ex: If i want to store the indexes 0,3,5 then i store 101001 i.e. 41 as an integer.
The problem is that maximum index that i have is 255 and using above technique i can store indexes
only till 64(using 64 bit integer). Is there any other way i can do this??
Thanks :-)
.NET has a built-in class for this kind of thing: BitArray
This will let you store a string of bits (in the form of bools) efficiently.
You can perform bitwise operations on BitArrays with the And, Or, Xor, and Not methods.
You can initialize a BitArray with bools, bytes, or ints. For example, you can initialize it with 00101100 like this:
BitArray bits = new BitArray(new byte[] { 0x2C }); // 0x2C == 00101100
You can use 2 bit indexes for every bit index.
Pratically with 10 bits (index from 1 to 10, set bits 0, 4, 8):
Single index:
i = 0100010001
Index1 = i
Two combined indexes:
i1 = 01000
i2 = 10001
Index2 = [i1, i2];
Index2.fragment_length = 5
Array
In pseudocode, to retrieve or set a bit
set(Index, bit) {
fragment = quotient(bit, Index.flagment_length); //quotient = integer division
bit_index = module(bit, Index.flagment_length); //index of the bit in the fragment
set(Index[fragment], bit-or(Index[Fragment], bit-shift-left(1 << bit_index))); //Set the bit indexes vector fragment with or-ing the appropriate bitmask
}
get(Index, bit) {
fragment = quotient(bit, Index.flagment_length); //quotient = integer division
bit_index = module(bit, Index.flagment_length); //index of the bit in the fragment
if (get(Index[fragment], bit-and(Index[Fragment], bit-shift-left(1 << bit_index))) > 0) then true else false; //Get the bit indexes vector fragment bit with and-ing the appropriate bitmask and return true or false
}
I hope to have understood your requirements!
In java the bit indexing made easy as the following little tutorial...
This class implements a vector of bits that grows as needed. Each component of the bit set has a boolean value. The bits of a BitSet are indexed by nonnegative integers. Individual indexed bits can be examined, set, or cleared. One BitSet may be used to modify the contents of another BitSet through logical AND, logical inclusive OR, and logical exclusive OR operations.
By default, all bits in the set initially have the value false.
Every bit set has a current size, which is the number of bits of space currently in use by the bit set. Note that the size is related to the implementation of a bit set, so it may change with implementation. The length of a bit set relates to logical length of a bit set and is defined independently of implementation.
Unless otherwise noted, passing a null parameter to any of the methods in a BitSet will result in a NullPointerException. A BitSet is not safe for multithreaded use without external synchronization.

Read/Write compressed binary data

I read all over the place people talk about compressing objects on a bit by bit scale. Things like "The first three bits represent such and such, then the next two represent this and twelve bits for that"
I understand why it would be desirable to minimize memory usage, but I cannot think of a good way to implement this. I know I would pack it into one or more integers (or longs, whatever), but I cannot envision an easy way to work with it. It would be pretty cool if there were a class where I could get/set arbitrary bits from an arbitrary length binary field, and it would take care of things for me, and I wouldn't have to go mucking about with &'s and |'s and masks and such.
Is there a standard pattern for this kind of thing?
From MSDN:
BitArray Class
Manages a compact array of bit values, which are represented as Booleans, where true indicates that the bit is on (1) and false indicates the bit is off (0).
Example:
BitArray myBitArray = new BitArray(5);
myBitArray[3] = true; // set bit at offset 3 to 1
BitArray allows you to set only individual bits, though. If you want to encode values with more bits, there's probably no way around mucking about with &'s and |'s and masks and stuff :-)
You might want to check out the BitVector32 structure in the .NET Framework. It lets you define "sections" which are ranges of bits within an int, then read and write values to those sections.
The main limitation is that it's limited to a single 32-bit integer; this may or may not be a problem depending on what you're trying to do. As dtb mentioned, BitArray can handle bit fields of any size, but you can only get and set a single bit at a time--there is no support for sections as in BitVector32.
What you're looking for are called bitwise operations.
For example, let's say we're going to represent an RGB value in the least significant 24 bits of an integer, with R being bits 23-16, G being bits 15-8, and B being bits 7-0.
You can set R to any value between 0 and 255 without effecting the other bits like this:
void setR(ref int RGBValue, int newR)
{
int newRValue = newR << 16; // shift it left 16 bits so that the 8 low-bits are now in position 23-16
RGBValue = RGBValue & 0x00FF; // AND it with 0x00FF so that the top 16 bits are set to zero
RGBValue = RGBValue | newRValue; // now OR it with the newR value so that the new value is set.
}
By using bitwise ANDs and ORs (and occasionally more exotic operations) you can easily set and clear any individual bit of a larger value.
Rather than using toolkit or platform specific wrapper classes I think you are better off biting the bullet and learning your &s and |s and 0x04s and how all the bitwise operators work. By and large that's how its done for most projects, and the operations are extremely fast. The operations are pretty much identical on most languages so you won't be stuck dependant on some specific toolkit.

Categories

Resources