Skip to content

Commit 611af7b

Browse files
committed
Cleanup (#114).
It should now be possible (in theory) to sieve every value in 0 through UInt.max on setup. This means that the sieve's stride may no longer fit in UInt, so I removed it. I also had to update some preconditions in Cache.init and Sieve/increment(). Would you ever sieve 0 through UInt.max on setup? Doubt it. But the restriction (in theory) was awkward.
1 parent 261e3fa commit 611af7b

File tree

2 files changed

+22
-21
lines changed

2 files changed

+22
-21
lines changed

Sources/NBKCoreKit/Models/NBKPrimeSieve.swift

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public final class NBKPrimeSieve: CustomStringConvertible {
7373
///
7474
/// - Note: A page contains `1` odd number per bit in `cache`.
7575
///
76-
/// - Note: The defaults strike balance between size and performance.
76+
/// - Note: The defaults strike a balance between size and performance.
7777
///
7878
public init(cache: Cache = .KiB(32), wheel: Wheel = .x07, culls: Culls = .x11) {
7979
self.cache = cache
@@ -96,11 +96,6 @@ public final class NBKPrimeSieve: CustomStringConvertible {
9696
self.state.elements
9797
}
9898

99-
/// The number of elements sieved per `increment()`.
100-
@inlinable public var stride: UInt {
101-
self.cache.count &<< 1 as UInt // OK, see size
102-
}
103-
10499
//=------------------------------------------------------------------------=
105100
// MARK: Utilities
106101
//=------------------------------------------------------------------------=
@@ -122,16 +117,15 @@ extension NBKPrimeSieve {
122117

123118
/// Sieves the next page of ``NBKPrimeSieve/increment`` number of values.
124119
@inline(never) @inlinable public func increment() {
125-
precondition(!self.limit.addingReportingOverflow(self.stride).overflow)
126120
Swift.assert((self.cache.base).allSatisfy({ $0.onesComplement().isZero }))
127121
//=--------------------------------------=
128-
let start = self.limit &+ 00000000002
129-
let limit = self.limit &+ self.stride
122+
let start = self.limit &+ 0000000000000002
123+
let limit = self.limit &+ self.cache.count * 2 as UInt // traps max sieve (!)
130124
var inner = NBK.CyclicIterator(self.wheel.increments)!
131125
//=--------------------------------------=
132126
// mark composites not hit by the wheel
133127
//=--------------------------------------=
134-
let iteration = 1 &+ NBK.PBI.quotient(dividing: NBK.ZeroOrMore(self.limit &>> 1), by: NBK.PowerOf2(bitWidth: UInt.self))
128+
let iteration = 1 &+ NBK.PBI.quotient(dividing: NBK.ZeroOrMore(self.limit &>> 1 as UInt), by: NBK.PowerOf2(bitWidth: UInt.self))
135129

136130
for pattern in self.culls.patterns {
137131
var pattern = NBK.CyclicIterator(pattern)!
@@ -189,13 +183,13 @@ extension NBKPrimeSieve {
189183
}
190184

191185
@inline(never) @inlinable static func makeInitialState(_ cache: inout Cache, _ wheel: Wheel, _ culls: Culls) -> State {
192-
Swift.assert(wheel.primes.first == 000000000000000002)
193-
Swift.assert(culls.primes.first != 000000000000000002)
194-
precondition(wheel.primes.last! <= culls.primes.last!, "must cull each element in wheel")
186+
Swift.assert(wheel.primes.first == 00000000000000002)
187+
Swift.assert(culls.primes.first != 00000000000000002)
188+
precondition(wheel.primes.last! <= culls.primes.last!, "must cull multiples of each element in wheel")
195189
Swift.assert(wheel.primes[1...].allSatisfy(culls.primes.contains))
196190
Swift.assert(cache.base.allSatisfy { $0.onesComplement().isZero })
197191
//=--------------------------------------=
198-
let limit = cache.count * 2 - 1 // OK, see size
192+
let limit = cache.count &* 2 &- 1 // OK, see size
199193
var outer = NBK.CyclicIterator(wheel.increments)!
200194
var inner = NBK.CyclicIterator(wheel.increments)!
201195
var state = State(limit: UInt.max, elements: [])
@@ -311,13 +305,20 @@ extension NBKPrimeSieve {
311305

312306
/// ### Development
313307
///
314-
/// It fits at most `Int.max` bits so the odd number stride fits.
308+
/// The maximum number of bits is `Int.max + 1`. This is the number of bits
309+
/// needed to represent each odd number in `0 ... UInt`. The maximum stride
310+
/// is therefore not representable by `UInt`. But, the sieve is still valid
311+
/// if there is proper overflow checking past setup.
312+
///
313+
/// - Requires: `words > 0`
315314
///
316-
/// - Requires: `2 * UInt.bitWidth * words <= UInt.max`
315+
/// - Requires: `words * UInt.bitWidth * 2 <= UInt.max + 1`
317316
///
318317
@inlinable init(words: Int) {
319-
precondition(words <= (Int.max / UInt.bitWidth),
320-
"the prime sieve's increment must fit in UInt")
318+
let limit = (UInt.max / UInt(UInt.bitWidth * 2)) + 1
319+
Swift.assert(limit >= 1 && limit &* UInt(UInt.bitWidth * 2) == 0 as UInt)
320+
precondition(UInt(words) >= 00001, "prime sieve's stride must be greater than zero")
321+
precondition(UInt(words) <= limit, "prime sieve's stride must not exceed number of elements in UInt")
321322
self.base = Array(repeating: UInt.max, count: words)
322323
}
323324

@@ -329,7 +330,7 @@ extension NBKPrimeSieve {
329330
@inlinable var count: UInt {
330331
UInt(bitPattern: self.base.count) &* UInt(bitPattern: UInt.bitWidth)
331332
}
332-
333+
333334
/// The bit at the given `index`.
334335
@inlinable subscript(index: UInt) -> Bool {
335336
let index = NBK.PBI.dividing(NBK.ZeroOrMore(index), by: NBK.PowerOf2(bitWidth: UInt.self))

Tests/NBKCoreKitTests/Models/NBKPrimeSieve.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,10 @@ final class NBKPrimeSieveTests: XCTestCase {
292292
//=------------------------------------------------------------------------=
293293

294294
func testSettings() {
295-
let/**/ cache: T.Cache = .words( 256 / UInt.bitWidth)
295+
let/**/ cache: T.Cache = T.Cache.words(0256 / UInt.bitWidth)
296296
for/**/ wheel: T.Wheel in [.x02, .x03, .x05, .x07, .x11] {
297297
for culls: T.Culls in [.x11, .x13, .x17, .x19, .x23, .x29, .x31] {
298-
let ((sieve)) = T(cache: cache, wheel: wheel, culls: culls)
298+
let ((sieve)) = T(cache: cache, wheel: wheel, culls: culls)
299299
check(sieve, limit: 0511, count: 0097, last: 0509)
300300

301301
sieve.increment()

0 commit comments

Comments
 (0)