Search code examples
c#bitmaskushort

Using Bitmask to read first 2 bits of a ushort in C#


I have an array of ushorts and want to iterate over the array and check if the first two bits of that ushort are 11 if so I want to clear them. However the bit mask I am using to read the first two bits in my conditional are not working properly and the if statement does not trigger when the first two bits are 11

static public void trimData(ushort[] rawData)
{
   for(int i = 0; i < rawData.Length; i++)
   {
     if (((ushort)(rawData[i] & (1 << 15)) == 1) && ((ushort)(rawData[i] & (1 << 14)) == 1))
     {
        rawData[i] = (ushort)(rawData[i]&~(1<<15));
        rawData[i] = (ushort)(rawData[i]&~(1<<14));
     }
   }

}

How can I use bitmasks to do this correctly?


Solution

  • You can shift these bits to have them being the rightmost ones and then mask with 0b11:

     // drop all bits except topmost ones 16 - 14 == 2 which are now the rightmost
     int bits = (rawData[i] >> 14) & 0b11; 
    
     if (bits == 0b11) {
       // Both bits are set
     }
    

    To clear these bits you use XOR ^ (since 1 ^ 1 == 0):

     int mask = 0b11 << 14;
    
     // remove 14th and 15th set bits  
     rawData[i] = (ushort)(rawData[i] ^ mask);
    

    Let's combine these parts:

     if (((rawData[i] >> 14) & 0b11) == 0b11)
       rawData[i] = (ushort)(rawData[i] ^ (0b11 << 14));
    

    Finally, the method can be

    public static void trimData(ushort[] rawData) {
      if (rawData is null)
        throw new ArgumentNullException(nameof(rawData));
    
      for (int i = 0; i < rawData.Length; i++) 
        if (((rawData[i] >> 14) & 0b11) == 0b11)
          rawData[i] = (ushort)(rawData[i] ^ (0b11 << 14));
    }