0
votes

I would like to drastically improve the time performance of an operation I would best describe as a bit wise operation. The following is a constructor for a BitFile class, taking three BitFile as parameters. Whichever bit the first and second parameter (firstContender and secondContender) agree on is taken from firstContender into the BitFile being constructed. Whichever bit they don't agree on is taken from the supportContender.

data is the class-field storing the result and the backbone of the BitFile class.

compare(byte,byte) returns true if both bytes are identical in value.

add(byte,int) takes a byte representing a bit and the index within the bit to extract, a second class-field "index" is used and incremented in add(byte,int) to put the next bit in location.

'BitFile.get(int)' returns a byte with just a specific bit being one, if it is one, BitFile.get(9) would return a byte with value 2 if the second bit of the second byte is a one, otherwise 0.

Xor bit wise operation can quickly tell me which bits are different in the two BitFile. Is there any quick way to use the result of a Xor, where all it's zeroes are represented by the firstContender's equivalent bit and all the one's are represented by the supportContender's equivalent bit, something like a three operand Bit Wise operator?

public BitFile(
BitFile firstContender,BitFile secondContender,BitFile supportContender)
{
    if(firstContender.getLength() != secondContender.getLength())
    {
        throw new IllegalArgumentException(
        "Error.\n"+
        "In BitFile constructor.\n"+
        "Two BitFiles must have identical lengths.");
    }
    BitFile randomSet = supportContender;
    int length = firstContender.getLength();
    data = new byte[length];
    for(int i = 0; i < length*8;i++)
    {
        if(compare(firstContender.get(i),secondContender.get(i)))
        {
            add(firstContender.get(i),i%8);
        }
        else
        {
            add(randomSet.get(i),i%8);
        }
    }
}
1
For bitwise operation of large sets I suggest using BitSet which use 1 bit per value and can be much faster as well as smaller.Peter Lawrey

1 Answers

1
votes

I found this question fairly confusing, but I think what you're computing is like this:

merge(first, second, support) = if first == second then first else support

So just choose where the bit comes from depending on whether the first and second sources agree or not.

something like a three operand Bit Wise operator?

indeed something like that. But of course we need to implement it manually in terms of operations supported by Java. There are two common patterns in bitwise arithmetic to choose between two sources based on a third:

1) (a & ~m) | (b & m)
2) a ^ ((a ^ b) & m)

Which choose, for each bit, the bit from a where m is zero, and from b where m is one. Pattern 1 is easier to understand so I'll use it but it's simple to adapt the code to the second pattern.

As you predicted, the mask in this case will be first ^ second, so:

for (int i = 0; i < data.length; i++) {
    int m = first.data[i] ^ second.data[i];
    data[i] = (byte)((first.data[i] & ~m) | (support.data[i] & m));
}

The same thing could easily be done with an array of int or long which would need fewer operations to process the same amount of data.