//␊ |
// 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␊ |