File tree Expand file tree Collapse file tree 2 files changed +34
-5
lines changed
Tests/SwiftAlgorithmsTests Expand file tree Collapse file tree 2 files changed +34
-5
lines changed Original file line number Diff line number Diff line change @@ -94,7 +94,8 @@ internal func nextW<G: RandomNumberGenerator>(
94
94
internal func nextOffset< G: RandomNumberGenerator > (
95
95
w: Double , using rng: inout G
96
96
) -> Int {
97
- Int ( Double . log ( . random( in: 0 ..< 1 , using: & rng) ) / . log( 1 - w) )
97
+ let offset = Double . log ( . random( in: 0 ..< 1 , using: & rng) ) / . log( onePlus: - w)
98
+ return offset < Double ( Int . max) ? Int ( offset) : Int . max
98
99
}
99
100
100
101
extension Collection {
@@ -201,10 +202,10 @@ extension Sequence {
201
202
w *= nextW ( k: k, using: & rng)
202
203
203
204
// Find the offset of the next element to swap into the reservoir.
204
- var offset = nextOffset ( w: w, using: & rng) + 1
205
+ var offset = nextOffset ( w: w, using: & rng)
205
206
206
- // Skip over `offset - 1 ` elements to find the selected element.
207
- while offset > 1 , let _ = iterator. next ( ) {
207
+ // Skip over `offset` elements to find the selected element.
208
+ while offset > 0 , let _ = iterator. next ( ) {
208
209
offset -= 1
209
210
}
210
211
guard let nextElement = iterator. next ( ) else { break }
Original file line number Diff line number Diff line change 10
10
//===----------------------------------------------------------------------===//
11
11
12
12
import XCTest
13
- import Algorithms
13
+ @ testable import Algorithms
14
14
15
15
func validateRandomSamples< S: Sequence > (
16
16
_ samples: [ Int : Int ] ,
@@ -95,4 +95,32 @@ final class RandomSampleTests: XCTestCase {
95
95
let sample2c = c. randomStableSample ( count: k, using: & generator)
96
96
XCTAssertEqual ( sample1c, sample2c)
97
97
}
98
+
99
+ func testRandomSampleRandomEdgeCasesInternal( ) {
100
+ struct ZeroGenerator : RandomNumberGenerator {
101
+ mutating func next( ) -> UInt64 { 0 }
102
+ }
103
+ var zero = ZeroGenerator ( )
104
+ _ = nextOffset ( w: 1 , using: & zero) // must not crash
105
+
106
+ struct AlmostAllZeroGenerator : RandomNumberGenerator {
107
+ private var forward : SplitMix64
108
+ private var count : Int = 0
109
+
110
+ init ( seed: UInt64 ) {
111
+ forward = SplitMix64 ( seed: seed)
112
+ }
113
+
114
+ mutating func next( ) -> UInt64 {
115
+ defer { count &+= 1 }
116
+ if count % 1000 == 0 { return forward. next ( ) }
117
+ return 0
118
+ }
119
+ }
120
+
121
+ var almostAllZero = AlmostAllZeroGenerator ( seed: 0 )
122
+ _ = s. randomSample ( count: k, using: & almostAllZero) // must not crash
123
+ almostAllZero = AlmostAllZeroGenerator ( seed: 0 )
124
+ _ = c. randomSample ( count: k, using: & almostAllZero) // must not crash
125
+ }
98
126
}
You can’t perform that action at this time.
0 commit comments