Fastest way to XOR two specific bit indexes in two bytes - c#

This is in C#. I was hoping I could do something like the following.
byte byte1 = 100;
byte byte2 = 100;
byte1[1] = byte1[1] ^ byte2[6]; // XOR bit at index 1 against bit at index 6
However, I am currently stuck at:
if ((byte2 ^ (byte)Math.Pow(2, index2)) < byte2)
byte1 = (byte)(byte1 ^ (byte)Math.Pow(2, index1));
Is there a faster way, possibly something similar to what I typed at the top?
Edit:
I had never heard of any of the bitwise operators other than XOR. That's why the original solution had the bizarre Math.Pow() calls. I've already improved my solution considerably according to my benchmarking of millions of loop iterations. I'm sure I'll get it faster with more reading. Thanks to everybody that responded.
byte2 = (byte)(byte2 << (7 - index2));
if (byte2 > 127)
{
byte buffer = (byte)(1 << index1);
byte1 = (byte)(byte1 ^ buffer);
}

Bytes are immutable, you can't change a bit of the byte as if it was an array. You'd need to access the bits through masks (&) and shifts (<< >>), then create a new byte containing the result.
// result bit is the LSB of r
byte r = (byte)((byte1 >> 1 & 1) ^ (byte2 >> 6 & 1));
The specific mask 1 will erase any bit except the right most (LSB).

Related

Reading Two Int4 from a Byte into two Seperate Bytes and Vice Versa

Okay so this may sound ridiculous, but as a personal project, I am trying to re-create a TCP networking protocol in C#.
Every TCP packet received has a header that must start with with two Int4 (0 - 15) forming a single Byte. I think using bitwise operators I have extracted the two Int4 from the byte:
Byte firstInt4 = headerByte << 4;
Byte secondInt4 = headerByte >> 4;
The issue is that I now need to be able to write two Int4 to a single Byte, but I have no idea how to do this.
Yes, bitwise operations will do:
Split:
byte header = ...
byte firstInt4 = (byte) (header & 0xF); // 4 low bits
byte secondInt4 = (byte) (headerByte >> 4); // 4 high bits
Combine:
byte header = (byte) ((secondInt4 << 4) | firstInt4);
An int4 is called a "nibble": half a byte is a nibble. :)
Something like:
combinedByte = hiNibble;
combinedByte << 4; // Make space for second nibble.
combinedByte += loNibble;
should do what you want.

Confirmation of Reverse Reciprocal CRC-8 Value?

I've spent quite a bit of time trying to confirm the type of CRC-8 algorithm used in ASCII data communications between two devices. I have confirmed that the CRC is calculated on the 0x02 Start of text byte + the next byte of data. An Interface Design Document that I have describing one device specifies the use of a 0xEA polynomial with an initial value of 0xFF. An example of one captured message is below:
Input Bytes: 0x02 0x41
CRC Result: b10011011 or 0x9B
Going into the problem, I had little to no knowledge of the inner working of a typical CRC algorithm. Initially, I tried hand calculation against the input bytes to confirm my understanding of the algo before attempting a code solution. This involved XORing the 1st input byte with my 0xFF initial value and then skipping to the second input byte to continue the XOR operations.
Having tried multiple times to confirm the CRC through typical XOR operations while shifting the MSB left out of the register during each step, I could never get the results I wanted. Today, I realized that the 0xEA polynomial is also considered to be a reversed reciprocal of the 0xD5 poly with an implied 1+x^8 that is commonly used in CRC-8 algos. How does this fact change how I would go about manually calculating the CRC? I've read that in some instances a reverse leads to the algo right shifting bits instead of left shifting?
The polynomial is x^8+x^7+x^5+x^3+x^2+x+1 => 01AF bit reversed to x^8+x^7+x^6+x^5+x^3+x+1 => 0x1EB. Example code where the conditional XOR is done after the shift, so the XOR value is 0x1EB>>1 = 0xF5. A 256 byte table lookup could be used to replace the inner loop.
using System;
namespace crc8r
{
class Program
{
private static byte crc8r(byte[] bfr, int bfrlen)
{
byte crc = 0xff;
for (int j = 0; j < bfrlen; j++)
{
crc ^= bfr[j];
for (int i = 0; i < 8; i++)
// assumes twos complement math
crc = (byte)((crc>>1)^((0-(crc&1))&0xf5));
}
return crc;
}
static void Main(string[] args)
{
byte[] data = new byte[3] {0x02, 0x41, 0x00};
byte crc;
crc = crc8r(data, 2); // crc == 0x9b
Console.WriteLine("{0:X2}", crc);
data[2] = crc;
crc = crc8r(data, 3); // crc == 0x00
Console.WriteLine("{0:X2}", crc);
return;
}
}
}
Regarding "EA", if the polynomial is XOR'ed before the shift, 0x1EB (or 0x1EA since bit 0 will be shifted off and doesn't matter) is used. XOR'ing before the shift requires 9 bits, or a post shift OR or XOR of 0x80, while XOR'ing after the shift only requires 8 bits.
Example line of code using 0x1eb before the shift:
crc = (byte)((crc^((0-(crc&1))&0x1eb))>>1);

Modify specific bit in byte

I need to modify (!not toggle XOR!) specific bit in byte value. I have:
source byte (e.g. b11010010);
index of bit to modify (e.g. 4);
new value of bit (0 or 1).
Now, what I need. If new value is 0, then bit[4] must be set to 0. If new value is 1, then bit[4] must be set to 1.
General part:
var bitIndex = 4;
var byte = b11010010;
var mask = 1 << bitIndex;
var newValue = 1;
This is the easiest way to do this:
if(newValue == 1)
byte |= mask; // set bit[bitIndex]
else
byte &= ~mask; // drop bit[bitIndex]
Another way allows to do this without if else statement, but look to hard to understand:
byte = byte & ~mask | (newValue << bitIndex) & mask
Here, first AND drops bit[bitIndex], second AND calculates new value for bit[bitIndex], and OR set bit[bitIndex] to calculated value, not matter is it 0 or 1.
Is there any easier way to set specific bit into given value?
(newValue << bitIndex) only has a single bit set, there's no need for & mask.
So you have just 5 operations.
byte = byte & ~(1 << bitIndex) | (newValue << bitIndex); // bitIndex'th bit becomes newValue
It's still complex enough to be worth a comment, but easy to see that the comment is correct because it's two easily recognized operations chained together (unlike the current accepted answer, which requires every reader to sit down and think about it for a minute)
The canonical way to do this is:
byte ^= (-newValue ^ byte) & (1 << n);
Bit number n will be set if newValue == 1, and cleared if newValue == 0

C#: How to concatenate bits to create an UInt64?

I'm trying to create a hashing function for images in order to find similar ones from a database.
The hash is simply a series of bits (101110010) where each bit stands for one pixel. As there are about 60 pixels for each image I assume it would be best to save this as an UInt64.
Now, when looping through each pixel and calculating each bit, how can I concatenate those and save them as a UInt64?
Thanks for you help.
Use some bit twiddling:
long mask = 0;
// For each bit that is set, given its position (0-63):
mask |= 1 << position;
You use bitwise operators like this:
ulong it1 = 0;
ubyte b1 = 0x24;
ubyte b2 = 0x36;
...
it1 = (b1 << 48) | (b2 << 40) | (b3 << 32) .. ;
Alternatively you can use the BitConvert.Uint64() function to quickly convert a byte array to int64. But are you sure the target is of 8bytes long?

How to extract bytes from a byte array starting at a bit position not on a byte boundary c#

I have a byte array in c#. I need to pull out a certain number of bytes starting at a bit position that may not lie on a byte boundary.
Write a little helper method which uses the shift operators to get a byte out
e.g.
byte[] x = new[] {0x0F, 0xF0}
result = x[0] << 4 | x[1] >> 4;
returns 8 bits from the 5th bit position 0xFF
You could easily vary the position using the modulo operator %
a byte is the minimal alignment you can read with the standard stream readers in .NET
If you want to read bits, you need to use bitwise operators and masks to determine if a bit is on (1) or off (0).
But, this means you could use boolean true/false to tell what the contents of a byte are. One way is to read the bits into a boolean enumeration. Something like this extension method could work:
public static IEnumerable<bool> BitsToBools(IEnumerable<byte> input)
{
int readByte;
while((readByte = input.MoveNext()) >= 0)
{
for(int i = 7; i >= 0; i--) // read left to right
yield return ((readByte >> i) & 1) == 1;
}
}
You could add a startIndex and a count to the extension method if you want, or pass in the range from the calling method.

Categories

Resources