tags:

views:

93

answers:

2

I am a little confused as to what is being accomplished by this method. It seems to be attempting to break bytes into nibbles and reassemble the nibbles with nibbles from other bytes to form new bytes and then return a new sequence of bytes.

However, I didn't think, you could take nibbles from a byte using modulus and subtraction and division, nor reassemble them with simple multiplication and addition.

I want to better understand what how this method works, and what it is doing, so I can get some comments around it and then see if it can be converted to make more sense using more more standard methods of nibbling bytes and even take advantage of .Net 4.0 if possible.

private static byte[] Process(byte[] bytes)
{
    Queue<byte> newBytes = new Queue<byte>();

    int phase = 0;
    byte nibble1 = 0;
    byte nibble2 = 0;
    byte nibble3 = 0;

    int length = bytes.Length-1;

    for (int i = 0; i < length; i++)
    {
        switch (phase)
        {
            case 0:
                nibble1 = (byte)((bytes[i] - (bytes[i] % 4)) / 4);
                nibble2 = (byte)(byte[i] % 4);
                nibble3 = 0;
                break;
            case 1:
                nibble2 = (byte)((nibble2 * 4) + (bytes[i] - (bytes[i] % 16))/16);
                nibble3 = (byte)(bytes[i] % 16);
                if (i < 4)
                {
                    newBytes.Clear();
                    newBytes.Enqueue((byte)((16 * nibble1) + nibble2));
                }
                else
                    newBytes.Enqueue((byte)((16 * nibble1) + nibble2));
                break;
            case 2:
                nibble1 = nibble3;
                nibble2 = (byte)((bytes[i] - (bytes[i] % 4)) / 4);
                nibble3 = (byte)(bytes[i] % 4);
                newBytes.Enqueue((byte)((16 * nibble1) + nibble2));
                break;
            case 3:
                nibble1 = (byte)((nibble3 * 4) + (bytes[i] - (bytes[i] % 16))/16);
                nibble2 = (byte)(bytes[i] % 16);
                newBytes.Enqueue((byte)((16 * nibble1) + nibble2));
                break;
        }

        phase = (phase + 1) % 4;
    }

    return newBytes.ToArray();
}
+3  A: 

Multiplication by 2 is the same as shifting bits one place to the left. (So multiply by 4 is shifting 2 places, and so on).

Division by 2 is the same as shifting bits one place to the right.

The modulus operator is being used to mask parts of the values. Modulus N where N = 2^p, will give you the value contained in (p-1) bits of the original value. So

value % 4

Would be the same as

value & 7    // 7 the largest value you can make with 3 bits (4-1). 4 + 2 +1.

Addition and subtraction can be used to combine the values. For instance if you know n and z to be 4-bit values, then both the following statements would combine them into one byte, with n placed in the upper 4 bits:

value = (n * 16) + z;

Versus

value = (n << 4) | z;
driis
Would there be a bitwise equivalent for % 4 and % 16?
Rodney Foley
Yes, see edited answer
driis
what is the purpose of i < 4 in the phase 1? Why is it clearing the newBytes before adding? Because of how the phases are computed does this only happen once and isn't really needed?
Rodney Foley
The clearing will only happen once when working on the second byte (i=1) when the phase would be 1, the next time the phase is 1 it will be processing byte 5.
Maggie
It looks like it is taking every 4 bytes shifting them, then storing into 3 bytes. For example compressing 16 bytes into 12.
Maggie
+2  A: 

I am not entirely sure, but the code appears to be rearranging the nibbles in each byte and flipping them (so 0xF0 becomes 0x0F). It may be trying to compress or encrypt the bytes - difficult to tell without representative input.

In regards to the different things happening in the function:

  • Dividing by 4 is the same a rightshifting twice (>> 2)
  • Dividing by 16 is the same a rightshifting four times (>> 4)
  • Multiplying by 4 is the same a leftshifting twice (<< 2)
  • Multiplyingby 16 is the same a leftshifting four times (<< 4)

These parts reconstruct a byte from nibbles, the first nibble is placed in the higher order part, the second in the lower order:

(byte)((16 * nibble1) + nibble2)

So if nibble1 is 0x0F and nibble2 is 0x0C, the operation results in a leftshift of the nibble1 by 4, resulting in 0xF0 then nibble2 is added, resulting in 0xFF.

Oded
What is the purpose of i < 4 in the phase 1? Why is it clearing the newBytes before adding? Because of how the phases are computed does this only happen once and isn't really needed?
Rodney Foley
@Creepy Gnome - I agree, it does appear redundant. Possibly an artifact left during development of the code.
Oded