// // BitArray.m // oneIP // // Created by Bret Deasy on 7/16/13. // Copyright (c) 2013 Bret Deasy. All rights reserved. // #import "BitArray.h" @implementation BitArray @synthesize bitVector; /** Initialize with empty bitVector **/ - (id)init { self = [super init]; if (self) { bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 0); } return self; } /** Returns a BitArray object initialized by copying the bits from another given BitArray. **/ - (id)initWithBitArray:(BitArray *)bitArray { return [self initWithBitVector:[bitArray bitVector]]; } /** Initialize with capacity-sized bitVector containing all zeroes. **/ - (id)initWithCount:(CFIndex)count { self = [super init]; if (self) { bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 0); [self setCount:count]; } return self; } /** Initializer from a given string of 0s and/or 1s. */ - (id)initWithString:(NSString *)bitString { self = [super init]; if (self) { int length = [bitString length]; CFMutableBitVectorRef _bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, length); CFBitVectorSetCount(_bitVector, length); for (int i = 0; i < length; i++) { int bitAtIndex = [bitString characterAtIndex:i] - 48; CFBitVectorSetBitAtIndex(_bitVector, i, bitAtIndex); } bitVector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, length, _bitVector); CFRelease(_bitVector); } return self; } /** Initializer from a given CFBitVectorRef. */ - (id)initWithBitVector:(CFMutableBitVectorRef)_bitVector { self = [super init]; if (self) { bitVector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, CFBitVectorGetCount(_bitVector), _bitVector); } return self; } /** Initialize from a given Int. Integer must be 0 or greater. **/ - (id)initWithInteger:(int)value { self = [super init]; if (self) { int capacity; if (value <= 0) { bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 1); CFBitVectorSetCount(bitVector, 1); } else { capacity = floor(log2(value))+1; bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); CFBitVectorSetCount(bitVector, capacity); for (int i = capacity - 1; i >= 0; i--) { CFBitVectorSetBitAtIndex(bitVector, i, (value & 1)); value>>=1; } } } return self; } /** Returns the AND of the receiver's bitVector and the passed BitArray's bitVector. */ - (BitArray *)bitArrayByANDingWithBitArray:(BitArray *)andBitArray { CFBit aBit; CFBit bBit; CFBit resultBit; [self equalizeBitVector:andBitArray]; int capacity = [self count]; CFMutableBitVectorRef resultBitArray = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); CFBitVectorSetCount(resultBitArray, capacity); for (int i = 0; i < capacity; i++) { aBit = CFBitVectorGetBitAtIndex(bitVector, i); bBit = CFBitVectorGetBitAtIndex([andBitArray bitVector], i); resultBit = aBit & bBit; CFBitVectorSetBitAtIndex(resultBitArray, i, resultBit); } BitArray *retBitArray = [[BitArray alloc] initWithBitVector:resultBitArray]; CFRelease(resultBitArray); return retBitArray; } /** Returns the OR of the receiver's bitVector with the passed BitArray's bitVector. **/ - (BitArray *)bitArrayByORingWithBitArray:(BitArray *)orBitArray { CFBit aBit; CFBit bBit; CFBit resultBit; [self equalizeBitVector:orBitArray]; int capacity = [self count]; CFMutableBitVectorRef resultBitArray = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); CFBitVectorSetCount(resultBitArray, capacity); for (int i = 0; i < capacity; i++) { aBit = CFBitVectorGetBitAtIndex(bitVector, i); bBit = CFBitVectorGetBitAtIndex([orBitArray bitVector], i); resultBit = aBit | bBit; CFBitVectorSetBitAtIndex(resultBitArray, i, resultBit); } BitArray *retBitArray = [[BitArray alloc] initWithBitVector:resultBitArray]; CFRelease(resultBitArray); return retBitArray; } /** Returns the NOT of the receiver's bitVector. **/ - (BitArray *)bitArrayByNOTingBitArray { CFBit bit; CFBit resultBit; int capacity = [self count]; CFMutableBitVectorRef resultBitArray = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); CFBitVectorSetCount(resultBitArray, capacity); for (int i = 0; i < capacity; i++) { bit = CFBitVectorGetBitAtIndex(bitVector, i); resultBit = !bit; CFBitVectorSetBitAtIndex(resultBitArray, i, resultBit); } BitArray *retBitArray = [[BitArray alloc] initWithBitVector:resultBitArray]; CFRelease(resultBitArray); return retBitArray; } /** Returns the number of bits in the receiver's bitVector. **/ - (int)count { return CFBitVectorGetCount(bitVector); } /** Sets the size of the receiver's bitVector **/ - (void)setCount:(CFIndex)count { CFBitVectorSetCount(bitVector, count); } /** Makes the receiver's bitVector and the parameter's of equal size **/ - (void)equalizeBitVector:(BitArray *)bitArray { int bitVectorCapacity = [self count]; int compareBitVectorCapacity = [bitArray count]; if (bitVectorCapacity < compareBitVectorCapacity) { [self padToCapacity:compareBitVectorCapacity]; } else if (bitVectorCapacity > compareBitVectorCapacity) { [bitArray padToCapacity:bitVectorCapacity]; } } /** Pads 0s to the left to make the bitVector's capacity match the parameter. */ - (void)padToCapacity:(int)capacity { int difference = capacity - [self count]; if (difference <= 0) { return; } CFMutableBitVectorRef tempVector = CFBitVectorCreateMutable(kCFAllocatorDefault, difference); CFBitVectorSetCount(tempVector, difference); BitArray *insertBitArray = [[BitArray alloc] initWithBitVector:tempVector]; [self insertBitArray:insertBitArray atIndex:0]; // for (int i = difference; i < capacity; difference++) // { // CFBitVectorSetBitAtIndex(tempVector, i, CFBitVectorGetBitAtIndex(bitVector, currIndex)); // currIndex++; // } // // bitVector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, capacity, tempVector); // CFRelease(tempVector); } /** Returns a new BitArray made by appending a given BitArray to the receiver. **/ - (BitArray *)bitArrayByAppendingBitArray:(BitArray *)bitArray { // return [[[BitArray alloc] initWithBitArray:self] bitArrayByAppendingBitArray:bitArray]; BitArray *retBitArray = [[BitArray alloc] initWithBitArray:self]; [retBitArray insertBitArray:bitArray atIndex:[self count]]; return retBitArray; } /** Returns BitArray containing the bitVector of the value parameter added to the receiver's bitVector. **/ - (BitArray *)bitArrayByAddingInteger:(int)value { return [self performMathOperation:Add withInt:value]; } /** Returns BitArray containing the bitVector of the value parameter subtracted from the receiver's bitVector. **/ - (BitArray *)bitArrayBySubtractingInteger:(int)value { return [self performMathOperation:Subtract withInt:value]; } /** Returns BitArray represented after performing the selected math operation with the given value on the receiver. **/ - (BitArray *)performMathOperation:(Operation)op withInt:(int)value { int capacity = [self count]; CFMutableBitVectorRef bits = CFBitVectorCreateMutable(kCFAllocatorDefault, capacity); CFBitVectorSetCount(bits, capacity); CFMutableBitVectorRef result = CFBitVectorCreateMutable(kCFAllocatorDefault, 2); CFBitVectorSetCount(result, 2); BitArray *valueBitArray = [[BitArray alloc] initWithInteger:value]; [self equalizeBitVector:valueBitArray]; for (int i = capacity - 1; i >= 0; i--) { int aBit = CFBitVectorGetBitAtIndex(bitVector, i); int bBit = CFBitVectorGetBitAtIndex([valueBitArray bitVector], i); int cBit = CFBitVectorGetBitAtIndex(result, 1); if (op == Add) { result = [self fullAdderWithaBit:aBit bBit:bBit cBit:cBit]; } else if (op == Subtract) { result = [self fullSubtractorWithaBit:aBit bBit:bBit cBit:cBit]; } CFBitVectorSetBitAtIndex(bits, i, CFBitVectorGetBitAtIndex(result, 0)); } BitArray *retBitArray = [[BitArray alloc] initWithBitVector:bits]; CFRelease(result); CFRelease(bits); return retBitArray; } /** Returns the sum bit and carry bit after performing an addition operation. **/ - (CFMutableBitVectorRef)fullAdderWithaBit:(BOOL)aBit bBit:(BOOL)bBit cBit:(BOOL)cBit { //bit0 = sum bit //bit1 = carry bit BOOL bit0 = (aBit ^ bBit) ^ cBit; BOOL bit1 = (aBit & bBit) | (bBit & cBit) | (aBit & cBit); CFMutableBitVectorRef retBitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 2); CFBitVectorSetCount(retBitVector, 2); CFBitVectorSetBitAtIndex(retBitVector, 0, bit0); CFBitVectorSetBitAtIndex(retBitVector, 1, bit1); return retBitVector; } /** Returns the sum bit and carry bit after performing an subtraction operation. **/ - (CFMutableBitVectorRef)fullSubtractorWithaBit:(BOOL)aBit bBit:(BOOL)bBit cBit:(BOOL)cBit { //bit0 = sum bit //bit1 = carry bit BOOL bit0 = aBit ^ bBit ^ cBit; BOOL bit1 = (cBit & (aBit ^ bBit)) | (!aBit & bBit); CFMutableBitVectorRef retBitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, 2); CFBitVectorSetCount(retBitVector, 2); CFBitVectorSetBitAtIndex(retBitVector, 0, bit0); CFBitVectorSetBitAtIndex(retBitVector, 1, bit1); return retBitVector; } /** Returns true if the receiver's bitVector is equal to that of the parameter's. **/ - (BOOL)equalToBitArray:(BitArray *)bitArray { CFBit bit; CFBit bitCompare; for (int i = 0; i < [self count]; i++) { bit = CFBitVectorGetBitAtIndex(bitVector, i); bitCompare = CFBitVectorGetBitAtIndex([bitArray bitVector], i); if (bit != bitCompare) { return NO; } } return YES; } /** Returns true if the receiver's bitVector is greater than or equal to that of the parameter's. **/ - (BOOL)greaterThanOrEqualToBitArray:(BitArray *)bitArray { return ([self greaterThanBitArray:bitArray] || [self equalToBitArray:bitArray]); } /** Returns true if the receiver's bitVector is less than or equal to that of the parameter's. **/ - (BOOL)lessThanOrEqualToBitArray:(BitArray *)bitArray { return ([self lessThanBitArray:bitArray] || [self equalToBitArray:bitArray]); } /** Returns true if the receiver's bitVector is greater than that of the parameter. **/ - (BOOL)greaterThanBitArray:(BitArray *)bitArray { [self equalizeBitVector:bitArray]; CFBit bit; CFBit compareBit; for (int i = [self count] - 1; i >= 0; i--) { bit = [self bitAtIndex:i]; compareBit = [bitArray bitAtIndex:i]; if (bit > compareBit) { return YES; } else if (bit < compareBit) { return NO; } } return NO; } /** Returns true of the receiver's bitVector is less than that of the parameter's **/ - (BOOL)lessThanBitArray:(BitArray *)bitArray { [self equalizeBitVector:bitArray]; CFBit bit; CFBit compareBit; for (int i = [self count]; i > 0; i--) { bit = [self bitAtIndex:i]; compareBit = [bitArray bitAtIndex:i]; if (bit < compareBit) { return YES; } else if (bit > compareBit) { return NO; } } return NO; } /** Returns the bit from the receiver's bitVector at the given index. **/ - (CFBit)bitAtIndex:(CFIndex)index { return CFBitVectorGetBitAtIndex(bitVector, index); } /** Sets the bit of the receiver's bitVector at the given index to the given value. **/ - (void)setBitAtIndex:(CFIndex)index toValue:(CFBit)bit { CFBitVectorSetBitAtIndex(bitVector, index, bit); } /** Inserts the given bitArray into the receiver at the given index. Receiver will expand as needed. **/ - (void)insertBitArray:(BitArray *)bitArray atIndex:(CFIndex)index { int count = [self count]; int newCount = count + [bitArray count]; int difference = [bitArray count]; int currIndex = 0; [self setCount:newCount]; for (int i = count-1; i >= index; i--) { [self setBitAtIndex:i+difference toValue:[self bitAtIndex:i]]; } for (int i = index; i < index+difference; i++) { [self setBitAtIndex:i toValue:[bitArray bitAtIndex:currIndex]]; currIndex++; } // if ([bitArray count] + index >= [self count]) // { // [self setCount:[bitArray count] + index + 1]; // } // for (int i = 0; i < [bitArray count]; i++) // { // CFBitVectorSetBitAtIndex(bitVector, index+i, [bitArray bitAtIndex:i]); // } } /** Returns the int value of the bits in the given range of the receiver's bitVector. **/ - (int)bitsInRange:(CFRange)range { int quotient = floor(range.length / 8); Byte *bytes = malloc(sizeof(Byte) * quotient); unsigned int byteValue = 0; CFBitVectorGetBits(bitVector, range, bytes); memcpy(&byteValue, bytes, quotient); //ensure big-endianness if (quotient > 1) { byteValue = htons(byteValue); } return byteValue; } /** Returns the string representation of the receiver. **/ - (NSString *)stringValue { NSString *retString = @""; for (int i = 0; i < [self count]; i++) { retString = [retString stringByAppendingFormat:@"%ld", [self bitAtIndex:i]]; } return retString; } -(void)dealloc { CFRelease(bitVector); } @end