@@ -54,11 +54,11 @@ public final class NBKPrimeSieve: CustomStringConvertible {
54
54
///
55
55
@usableFromInline var cache : Cache
56
56
57
- /// A cyclical pattern used to skip small prime multiples .
57
+ /// A cyclical pattern used to skip multiples of small primes .
58
58
@usableFromInline let wheel : Wheel
59
59
60
- /// A cyclical pattern used to cull small prime multiples .
61
- @usableFromInline let small : [ UInt ]
60
+ /// A cyclical pattern used to cull multiples of small primes .
61
+ @usableFromInline let small : Small
62
62
63
63
//=------------------------------------------------------------------------=
64
64
// MARK: Initializers
@@ -71,7 +71,7 @@ public final class NBKPrimeSieve: CustomStringConvertible {
71
71
public init ( size: Size ) {
72
72
self . cache = Cache ( size: size)
73
73
self . wheel = Wheel ( primes: [ 2 , 3 , 5 , 7 ] )
74
- self . small = Self . pattern ( primes: Array ( wheel. primes [ 1 ... ] ) )
74
+ self . small = Small ( primes: Array ( wheel. primes [ 1 ... ] ) )
75
75
self . state = Self . makeInitialState ( & cache, wheel, small)
76
76
}
77
77
@@ -94,11 +94,6 @@ public final class NBKPrimeSieve: CustomStringConvertible {
94
94
self . cache. count &<< 1 as UInt // OK, see size
95
95
}
96
96
97
- /// The number of bits in one number page.
98
- @inlinable public var size : UInt {
99
- self . cache. count
100
- }
101
-
102
97
//=------------------------------------------------------------------------=
103
98
// MARK: Utilities
104
99
//=------------------------------------------------------------------------=
@@ -135,7 +130,7 @@ public final class NBKPrimeSieve: CustomStringConvertible {
135
130
///
136
131
/// It represents at most `Int.max` bits so the odd number stride fits.
137
132
///
138
- /// - Requires: `words * UInt.bitWidth <= Int .max`
133
+ /// - Requires: `2 * UInt.bitWidth * words <= UInt .max`
139
134
///
140
135
@usableFromInline let words : Int
141
136
@@ -146,7 +141,7 @@ public final class NBKPrimeSieve: CustomStringConvertible {
146
141
@usableFromInline init ( @NBK . MoreThanZero words: Int ) {
147
142
self . words = words
148
143
precondition ( words <= ( Int . max / UInt. bitWidth) ,
149
- " number of elements per page must fit in UInt" )
144
+ " the prime sieve's increment must fit in UInt" )
150
145
}
151
146
152
147
//=--------------------------------------------------------------------=
@@ -155,7 +150,12 @@ public final class NBKPrimeSieve: CustomStringConvertible {
155
150
156
151
/// The size per page measured in KiB (i.e. 1024 B).
157
152
@inlinable public static func KiB( _ count: Int ) -> Self {
158
- Self ( words: 8 * 1024 / UInt. bitWidth * count)
153
+ Self ( words: count * ( 8 * 1024 / UInt. bitWidth) )
154
+ }
155
+
156
+ /// The size per page measured in words.
157
+ @inlinable public static func words( _ count: Int ) -> Self {
158
+ Self ( words: count)
159
159
}
160
160
}
161
161
}
@@ -182,7 +182,7 @@ extension NBKPrimeSieve {
182
182
// mark composites not hit by the wheel
183
183
//=--------------------------------------=
184
184
precull: do {
185
- var pattern = NBK . CyclicIterator ( self . small) !
185
+ var pattern = NBK . CyclicIterator ( self . small. pattern ) !
186
186
pattern. set ( iteration: 1 &+ NBK . PBI. quotient ( dividing: NBK . ZeroOrMore ( self . limit &>> 1 ) , by: NBK . PowerOf2 ( bitWidth: UInt . self) ) )
187
187
self . cache. sieve ( pattern: pattern)
188
188
}
@@ -236,7 +236,7 @@ extension NBKPrimeSieve {
236
236
}
237
237
}
238
238
239
- @inline ( never) @inlinable static func makeInitialState( _ cache: inout Cache , _ wheel: Wheel , _ small: [ UInt ] ) -> State {
239
+ @inline ( never) @inlinable static func makeInitialState( _ cache: inout Cache , _ wheel: Wheel , _ small: Small ) -> State {
240
240
Swift . assert ( cache. base. allSatisfy ( { $0. onesComplement ( ) . isZero } ) )
241
241
//=--------------------------------------=
242
242
let limit = cache. count * 2 - 1 // OK, see size
@@ -247,7 +247,7 @@ extension NBKPrimeSieve {
247
247
// mark each number in: 1, small
248
248
//=--------------------------------------=
249
249
cache. base [ cache. base. startIndex] = ~ 1
250
- cache. sieve ( pattern: NBK . CyclicIterator ( small) !)
250
+ cache. sieve ( pattern: NBK . CyclicIterator ( small. pattern ) !)
251
251
//=--------------------------------------=
252
252
// mark each number in: composites
253
253
//=--------------------------------------=
@@ -311,7 +311,7 @@ extension NBKPrimeSieve {
311
311
312
312
/// ### Development
313
313
///
314
- /// The possibility of size overflow is preconditioned by the size model.
314
+ /// Size overflow is prevented by the size model's preconditions .
315
315
///
316
316
@frozen @usableFromInline struct Cache {
317
317
@@ -325,19 +325,8 @@ extension NBKPrimeSieve {
325
325
// MARK: Initializers
326
326
//=--------------------------------------------------------------------=
327
327
328
- /// Rounds the given `size` down to at least one machine word.
329
- ///
330
- /// ### On a 64-bit machine
331
- ///
332
- /// ```
333
- /// bits: 000 ..< 064 -> 064
334
- /// bits: 064 ..< 128 -> 064
335
- /// bits: 128 ..< 192 -> 128
336
- /// bits: 192 ..< 256 -> 192
337
- /// ```
338
- ///
339
328
@inlinable init ( size: Size ) {
340
- self . base = Array ( repeating: UInt . max, count: Int ( size. words) )
329
+ self . base = Array ( repeating: UInt . max, count: size. words)
341
330
}
342
331
343
332
//=--------------------------------------------------------------------=
@@ -403,7 +392,7 @@ extension NBKPrimeSieve {
403
392
// MARK: State
404
393
//=--------------------------------------------------------------------=
405
394
406
- /// The primes used to create this wheel .
395
+ /// The primes used to create this instance .
407
396
@usableFromInline let primes : [ UInt ]
408
397
409
398
/// Returns the next `value` from the `index`.
@@ -484,54 +473,90 @@ extension NBKPrimeSieve {
484
473
}
485
474
486
475
//=----------------------------------------------------------------------------=
487
- // MARK: + Miscellaneous
476
+ // MARK: + Details x Small
488
477
//=----------------------------------------------------------------------------=
489
478
490
479
extension NBKPrimeSieve {
491
480
492
- //=------------------------------------------------------------------------=
493
- // MARK: Utilities
494
- //=------------------------------------------------------------------------=
481
+ //*========================================================================*
482
+ // MARK: * Small
483
+ //*========================================================================*
495
484
496
- @usableFromInline static func pattern( primes: [ UInt ] ) -> [ UInt ] {
497
- var pattern = [ UInt] ( repeating: UInt . max, count: Int ( primes. reduce ( 1 , * ) ) )
498
- var next : ( prime: UInt , product: UInt ) ; next. prime = primes. first!; next. product = next. prime
499
- var primeIndex = primes. startIndex; while primeIndex < primes. endIndex {
500
- //=----------------------------------=
501
- let current : ( prime: UInt , product: UInt ) = next
502
- var patternIndex = NBK . PBI. dividing ( NBK . ZeroOrMore ( current. prime &>> 1 ) , by: NBK . PowerOf2 ( bitWidth: UInt . self) )
503
- while patternIndex. quotient < current. prime {
504
- var chunk = UInt . zero
505
-
506
- while patternIndex. remainder < UInt . bitWidth {
507
- chunk |= 1 &<< patternIndex. remainder
508
- patternIndex. remainder &+= current. prime
509
- } ; chunk. formOnesComplement ( )
510
-
511
- var destination = patternIndex. quotient; while destination < current. product {
512
- pattern [ Int ( bitPattern: destination) ] &= chunk
513
- destination &+= current. prime
485
+ /// A cyclical pattern used to cull multiples of small primes.
486
+ ///
487
+ /// ### Development
488
+ ///
489
+ /// Consider multiple patterns formed by chunking:
490
+ ///
491
+ /// [03, 67], [05, 61], [07, 59],
492
+ /// [11, 53], [13, 47], [17, 43],
493
+ /// [19, 41], [23, 37], [29, 31],
494
+ ///
495
+ @frozen @usableFromInline struct Small {
496
+
497
+ //=--------------------------------------------------------------------=
498
+ // MARK: State
499
+ //=--------------------------------------------------------------------=
500
+
501
+ /// The primes used to create this instance.
502
+ @usableFromInline var primes : [ UInt ]
503
+
504
+ /// A cyclical pattern used to cull multiples of small primes.
505
+ @usableFromInline var pattern : [ UInt ]
506
+
507
+ //=--------------------------------------------------------------------=
508
+ // MARK: Initializers
509
+ //=--------------------------------------------------------------------=
510
+
511
+ @inlinable init ( primes: [ UInt ] ) {
512
+ self . primes = primes
513
+ self . pattern = Self . pattern ( primes: primes)
514
+ }
515
+
516
+ //=--------------------------------------------------------------------=
517
+ // MARK: Utilities
518
+ //=--------------------------------------------------------------------=
519
+
520
+ @usableFromInline static func pattern( primes: [ UInt ] ) -> [ UInt ] {
521
+ var pattern = [ UInt] ( repeating: UInt . max, count: Int ( primes. reduce ( 1 , * ) ) )
522
+ var next : ( prime: UInt , product: UInt ) ; next. prime = primes. first!; next. product = next. prime
523
+ var primeIndex = primes. startIndex; while primeIndex < primes. endIndex {
524
+ //=----------------------------------=
525
+ let current : ( prime: UInt , product: UInt ) = next
526
+ var patternIndex = NBK . PBI. dividing ( NBK . ZeroOrMore ( current. prime &>> 1 ) , by: NBK . PowerOf2 ( bitWidth: UInt . self) )
527
+ while patternIndex. quotient < current. prime {
528
+ var chunk = UInt . zero
529
+
530
+ while patternIndex. remainder < UInt . bitWidth {
531
+ chunk |= 1 &<< patternIndex. remainder
532
+ patternIndex. remainder &+= current. prime
533
+ } ; chunk. formOnesComplement ( )
534
+
535
+ var destination = patternIndex. quotient; while destination < current. product {
536
+ pattern [ Int ( bitPattern: destination) ] &= chunk
537
+ destination &+= current. prime
538
+ }
539
+
540
+ patternIndex. quotient &+= NBK . PBI. quotient ( dividing: NBK . ZeroOrMore ( patternIndex. remainder) , by: NBK . PowerOf2 ( bitWidth: UInt . self) )
541
+ patternIndex. remainder = NBK . PBI. remainder ( dividing: NBK . ZeroOrMore ( patternIndex. remainder) , by: NBK . PowerOf2 ( bitWidth: UInt . self) )
542
+ }
543
+ //=----------------------------------=
544
+ primes. formIndex ( after: & primeIndex)
545
+ //=----------------------------------=
546
+ if primeIndex < primes. endIndex {
547
+ next. prime = primes [ primeIndex]
548
+ next. product &*= next. prime
514
549
}
515
550
516
- patternIndex. quotient &+= NBK . PBI. quotient ( dividing: NBK . ZeroOrMore ( patternIndex. remainder) , by: NBK . PowerOf2 ( bitWidth: UInt . self) )
517
- patternIndex. remainder = NBK . PBI. remainder ( dividing: NBK . ZeroOrMore ( patternIndex. remainder) , by: NBK . PowerOf2 ( bitWidth: UInt . self) )
518
- }
519
- //=----------------------------------=
520
- primes. formIndex ( after: & primeIndex)
521
- //=----------------------------------=
522
- if primeIndex < primes. endIndex {
523
- next. prime = primes [ primeIndex]
524
- next. product &*= next. prime
525
- }
526
-
527
- var destination = current. product; while destination < next. product {
528
- for source in 0 as UInt ..< current. product {
529
- pattern [ Int ( bitPattern: destination) ] &= pattern [ Int ( bitPattern: source) ]
530
- destination += 1 as UInt
551
+ var destination = current. product; while destination < next. product {
552
+ for source in 0 as UInt ..< current. product {
553
+ pattern [ Int ( bitPattern: destination) ] &= pattern [ Int ( bitPattern: source) ]
554
+ destination += 1 as UInt
555
+ }
531
556
}
532
557
}
558
+
559
+ return pattern as [ UInt ] as [ UInt ] as [ UInt ]
533
560
}
534
-
535
- return pattern as [ UInt ] as [ UInt ] as [ UInt ]
536
561
}
537
562
}
0 commit comments