@@ -2329,12 +2329,40 @@ pub fn sample(from list: List(a), up_to n: Int) -> List(a) {
2329
2329
True -> [ ]
2330
2330
False -> {
2331
2331
let w = float . exponential ( log_random ( ) /. int . to_float ( n ) )
2332
- sample_loop ( list , reservoir , n , n , w ) |> dict . values
2332
+ dict . values ( sample_loop ( list , reservoir , n , w ) )
2333
2333
}
2334
2334
}
2335
2335
}
2336
2336
}
2337
2337
2338
+ fn sample_loop (
2339
+ list : List ( a) ,
2340
+ reservoir : Dict ( Int , a) ,
2341
+ k : Int ,
2342
+ w : Float ,
2343
+ ) -> Dict ( Int , a) {
2344
+ let skip = {
2345
+ let assert Ok ( log ) = float . logarithm ( 1.0 -. w )
2346
+ float . round ( float . floor ( log_random ( ) /. log ) )
2347
+ }
2348
+
2349
+ case drop ( list , skip ) {
2350
+ [ ] -> reservoir
2351
+ [ first , .. rest ] -> {
2352
+ let reservoir = dict . insert ( reservoir , int . random ( k ) , first )
2353
+ let w = w *. float . exponential ( log_random ( ) /. int . to_float ( k ) )
2354
+ sample_loop ( rest , reservoir , k , w )
2355
+ }
2356
+ }
2357
+ }
2358
+
2359
+ const min_positive = 2.2250738585072014e-308
2360
+
2361
+ fn log_random ( ) -> Float {
2362
+ let assert Ok ( random ) = float . logarithm ( float . random ( ) +. min_positive )
2363
+ random
2364
+ }
2365
+
2338
2366
/// Builds the initial reservoir used by Algorithm L.
2339
2367
/// This is a dictionary with keys ranging from `0` up to `n - 1` where each
2340
2368
/// value is the corresponding element at that position in `list`.
@@ -2367,33 +2395,3 @@ fn build_reservoir_loop(
2367
2395
}
2368
2396
}
2369
2397
}
2370
-
2371
- fn sample_loop (
2372
- list : List ( a) ,
2373
- reservoir : Dict ( Int , a) ,
2374
- k : Int ,
2375
- index : Int ,
2376
- w : Float ,
2377
- ) -> Dict ( Int , a) {
2378
- let skip = {
2379
- let assert Ok ( log_result ) = float . logarithm ( 1.0 -. w )
2380
- log_random ( ) /. log_result |> float . floor |> float . round
2381
- }
2382
-
2383
- let index = index + skip + 1
2384
-
2385
- case drop ( list , skip ) {
2386
- [ ] -> reservoir
2387
- [ first , .. rest ] -> {
2388
- let reservoir = dict . insert ( reservoir , int . random ( k ) , first )
2389
- let w = w *. float . exponential ( log_random ( ) /. int . to_float ( k ) )
2390
- sample_loop ( rest , reservoir , k , index , w )
2391
- }
2392
- }
2393
- }
2394
-
2395
- fn log_random ( ) -> Float {
2396
- let min_positive = 2.2250738585072014e-308
2397
- let assert Ok ( random ) = float . logarithm ( float . random ( ) +. min_positive )
2398
- random
2399
- }
0 commit comments