I perform Swift-style bitwise operations, which these codes are initially written in Objective-C / C. I use UnsafeMutablePointer to specify the starting index of a memory address and use UnsafeMutableBufferPointer to access an element inside a scope.
You can get the source Objective-C file here.
public init(size: Int) { self.size = size self.bitsLength = (size + 31) / 32 self.startIdx = UnsafeMutablePointer<Int32>.alloc(bitsLength * sizeof(Int32)) self.bits = UnsafeMutableBufferPointer(start: startIdx, count: bitsLength) } public func nextSet(from: Int) -> Int { if from >= size { return size } var bitsOffset = from / 32 var currentBits: Int32 = bits[bitsOffset] currentBits &= ~((1 << (from & 0x1F)) - 1).to32 while currentBits == 0 { if ++bitsOffset == bitsLength { return size } currentBits = bits[bitsOffset] } let result: Int = bitsOffset * 32 + numberOfTrailingZeros(currentBits).toInt return result > size ? size : result } func numberOfTrailingZeros(i: Int32) -> Int { var i = i guard i != 0 else { return 32 } var n = 31 var y: Int32 y = i << 16 if y != 0 { n = n - 16; i = y } y = i << 8 if y != 0 { n = n - 8; i = y } y = i << 4 if y != 0 { n = n - 4; i = y } y = i << 2 if y != 0 { n = n - 2; i = y } return n - Int((UInt((i << 1)) >> 31)) }
TestCase:
func testGetNextSet1() { // Passed var bits = BitArray(size: 32) for i in 0..<bits.size { XCTAssertEqual(32, bits.nextSet(i), "\(i)") } // Failed bits = BitArray(size: 34) for i in 0..<bits.size { XCTAssertEqual(34, bits.nextSet(i), "\(i)") } }
Can someone explain to me why the second test test fails, but the version of Objective-C passes?
Edit: As @vacawama pointed out: If you break testGetNextSet into 2 tests, pass both.
Edit2: When I run the tests using xctool , and the tests that call nextSet() when BitArray nextSet() will work while working.
source share