Skip to content

Commit 755a2f6

Browse files
committed
Provide implementation for lastBitSet.
1 parent f5993eb commit 755a2f6

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

Sources/NumberKit/BigInt.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,21 @@ public struct BigInt: Hashable,
837837
return i * UInt32.bitWidth
838838
}
839839

840+
/// Returns the last bit that is set in the two-complement form of this number if it is
841+
/// positive. For negative numbers, the last bit is computed of the negated number. For 0,
842+
/// this method returns 0.
843+
public var lastBitSet: Int {
844+
guard !self.isZero else {
845+
return 0
846+
}
847+
let number = self.negative ? self.not : self
848+
var i = number.uwords.count - 1
849+
while i >= 0 && number.uwords[i] == 0 {
850+
i -= 1
851+
}
852+
return i * UInt32.bitWidth + UInt32.bitWidth - number.uwords[i].leadingZeroBitCount
853+
}
854+
840855
/// Returns true if bit `n` is set
841856
public func isBitSet(_ n: Int) -> Bool {
842857
guard !self.isZero else {

Tests/NumberKitTests/BigIntTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ class BigIntTests: XCTestCase {
275275
XCTAssertEqual(x0.isBitSet(33), false)
276276
XCTAssertEqual(x0.isBitSet(34), false)
277277
XCTAssertEqual(x0.isBitSet(35), false)
278+
XCTAssertEqual(x0.lastBitSet, 32)
278279
let x1: BigInt = "64942224592110934030034938344746347339829000900128380"
279280
let bits1: Set<Int> =
280281
[2, 3, 4, 5, 6, 9, 10, 11, 13, 16, 17, 20, 22, 23, 24, 26, 27, 31, 33, 34, 35, 37,
@@ -285,6 +286,7 @@ class BigIntTests: XCTestCase {
285286
for i in 0..<300 {
286287
XCTAssertEqual(x1.isBitSet(i), bits1.contains(i))
287288
}
289+
XCTAssertEqual(x1.lastBitSet, 176)
288290
let x2: BigInt = "-1234567894257563210000294749382000039387453720000987383000032"
289291
let zeros1: Set<Int> =
290292
[0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14, 15, 19, 20, 21, 23, 24, 27, 28, 32, 34, 35,
@@ -296,6 +298,7 @@ class BigIntTests: XCTestCase {
296298
for i in 0..<400 {
297299
XCTAssertEqual(x2.isBitSet(i), !zeros1.contains(i))
298300
}
301+
XCTAssertEqual(x2.lastBitSet, 200)
299302
}
300303

301304
func testBitSet() {

0 commit comments

Comments
 (0)