Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Swift Numerics for elementary functions #28

Merged
merged 1 commit into from Oct 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion Package.swift
Expand Up @@ -20,11 +20,14 @@ let package = Package(
targets: ["Algorithms"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-numerics", from: "0.0.1"),
],
targets: [
.target(
name: "Algorithms",
dependencies: []),
dependencies: [
.product(name: "RealModule", package: "swift-numerics"),
]),
.testTarget(
name: "SwiftAlgorithmsTests",
dependencies: ["Algorithms"]),
Expand Down
26 changes: 8 additions & 18 deletions Sources/Algorithms/RandomSample.swift
Expand Up @@ -9,17 +9,9 @@
//
//===----------------------------------------------------------------------===//

// For log(_:) and exp(_:)
#if canImport(Glibc)
// For log(_:) and root(_:_:)
@_implementationOnly
import Glibc
#elseif canImport(ucrt)
@_implementationOnly
import ucrt
#elseif canImport(Darwin)
@_implementationOnly
import Darwin
#endif
import RealModule

//===----------------------------------------------------------------------===//
// randomStableSample(count:)
Expand Down Expand Up @@ -90,15 +82,15 @@ extension Collection {
// https://dl.acm.org/doi/pdf/10.1145/198429.198435

fileprivate func nextW<G: RandomNumberGenerator>(
k: Double, using rng: inout G
k: Int, using rng: inout G
) -> Double {
exp(log(Double.random(in: 0..<1, using: &rng)) / k)
Double.root(.random(in: 0..<1, using: &rng), k)
}

fileprivate func nextOffset<G: RandomNumberGenerator>(
w: Double, using rng: inout G
) -> Int {
Int(log(Double.random(in: 0..<1, using: &rng)) / log(1 - w))
Int(Double.log(.random(in: 0..<1, using: &rng)) / .log(1 - w))
}

extension Collection {
Expand Down Expand Up @@ -129,11 +121,10 @@ extension Collection {
result.append(self[i])
formIndex(after: &i)
}

let dk = Double(k)

while i < endIndex {
// Calculate the next value of w.
w *= nextW(k: dk, using: &rng)
w *= nextW(k: k, using: &rng)

// Find index of the next element to swap into the reservoir.
let offset = nextOffset(w: w, using: &rng)
Expand Down Expand Up @@ -198,10 +189,9 @@ extension Sequence {
result.append(el)
}

let dk = Double(k)
while true {
// Calculate the next value of w.
w *= nextW(k: dk, using: &rng)
w *= nextW(k: k, using: &rng)

// Find the offset of the next element to swap into the reservoir.
var offset = nextOffset(w: w, using: &rng) + 1
Expand Down