Tuesday, June 18, 2013

Performing Operations on Byte Arrays ( CSharp Solutions - C# )

When working with digital electronics, this can be easily accomplished with a few flip-flops and logic operators. To program something like this is just as easy - when one can rap their mind around it! I successfully wrote addition and subtraction methods that would perform these respective operations on raw byte arrays, many months ago. I lost the sources and had to really think how to replicate my results. Today I have not only successfully rewritten the source code but also composed them to add more than just one byte to an array of bytes.




Addition

public static byte[] Add(this byte[] A, byte[] B)
{
    List<byte> array = new List<byte>(A);
    for (int i = 0; i < B.Length; i++)

        array = _add_(array, B[i], i);

    return array.ToArray();
}
private static List<byte> _add_(List<byte> A, byte b, int idx = 0, byte rem = 0)
{
    short sample = 0;
    if (idx < A.Count)
    {
        sample = (short)((short)A[idx] + (short)b);
        A[idx] = (byte)(sample % 256);
        rem = (byte)((sample - A[idx]) % 255);
        if (rem > 0)
            return _add_(A, (byte)rem, idx + 1);
    }
    else A.Add(b);

    return A;
}


Subtraction

public static byte[] Subtract(this byte[] A, byte[] B)
{
    // find which array has a greater value for accurate
    // operation if one knows a better way to find which 
    // array is greater in value, do let me know. 
    // (MyArray.Length is not a good option here because
    // an array {255} - {100 000 000} will not yield a
    // correct answer.)
    int x = A.Length-1, y = B.Length-1;
    while (A[x] == 0 && x > -1) { x--; }
    while (B[y] == 0 && y > -1) { y--; }
    bool flag;
    if (x == y) flag = (A[x] > B[y]);
    else flag = (x > y);

    // using this flag, we can determine order of operations
    // (this flag can also be used to return whether
    // the array is negative)
    List<byte> array = new List<byte>(flag?A:B);
    int len = flag ? B.Length : A.Length;
    for (int i = 0; i < len; i++)
        array = _sub_(array, flag ? B[i] : A[i], i);

    return array.ToArray();
}
private static List<byte> _sub_(List<byte> A, byte b, int idx, byte rem = 0)
{
    short sample = 0;
    if (idx < A.Count)
    {
        sample = (short)((short)A[idx] - (short)b);
        A[idx] = (byte)(sample % 256);
        rem = (byte)(Math.Abs((sample - A[idx])) % 255);
        if (rem > 0)
            return _sub_(A, (byte)rem, idx + 1);
    }
    else A.Add(b);

    return A;
}


Multiplication

public static byte[] Multiply(this byte[] A, byte[] B)
{
    List<byte> ans = new List<byte>();

    
byte ov, res;
    int idx = 0;
    for (int i = 0; i < A.Length; i++)
    {
        ov = 0;
        for (int j = 0; j < B.Length; j++)
        {
            short result = (short)(A[i] * B[j] + ov);

            // get overflow (high order byte)
            ov = (byte)(result >> 8);
            res = (byte)result;
            idx = i + j;

            // apply result to answer array
            if (idx < (ans.Count))
                ans = _add_(ans, res, idx); else ans.Add(res);

        }
        // apply remainder, if any
        if(ov > 0) 
            if (idx+1 < (ans.Count)) 
                ans = _add_(ans, ov, idx+1); 
            else ans.Add(ov);
    }

    return ans.ToArray();
}

Division

- on the way -


Modulus

n = n - ( mod * ⌊ n / mod ⌋ )





To be used as follows: (Addition)
byte[] A = new byte[] { 0xFF };
byte[] B = BitConverter.GetBytes(235192);

byte[] C = A.Add(B);


4 comments:

  1. Hi teku, i like this amazing methods, but i can't understand how you made it, know you where can i learn more info about these functions? i mean how them work because i see bitwise operators i i don't know how them work for multiply, also %256 in _add confuse me :(

    i hope you can help me, and tahnks for these amazing functions :D

    ReplyDelete
    Replies
    1. When I built these methods, I first observed how we add, subtract, and multiply numbers in base 10. Then, I wrote instructions that mimicked the same process for base 256. (This is also somewhat similar to how older ALUs were implemented in computer processors.)

      Delete
  2. isn't there a way to do it if you use BigInteger methods? (Add,Sub,Mult?)
    byte[] a;
    meaning do BigInteger a = new BigInterger(a)
    and then the same to byte[] b and use BigInterger.Add(a,b)
    ??

    ReplyDelete
    Replies
    1. According to the documentation of Visual C#, Visual C++, and Java, there is, but my objective was not to use the BigInteger object but to explore its functionality. (The same reasons why students majoring in computer science are required to learn how to balance AVL Trees, sort arrays, and to perform a binary search.)

      Delete