add RNG
This commit is contained in:
21
Sources/EcgSynKit/SplitMix64.swift
Normal file
21
Sources/EcgSynKit/SplitMix64.swift
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
struct SplitMix64 : RandomNumberGenerator {
|
||||||
|
public typealias State = UInt64
|
||||||
|
public private(set) var state: State
|
||||||
|
|
||||||
|
init(state: UInt64) {
|
||||||
|
self.state = state
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func next() -> UInt64 {
|
||||||
|
state &+= 0x9E3779B97F4A7C15
|
||||||
|
var z = state
|
||||||
|
z = (z ^ (z >> 30)) &* 0xBF58476D1CE4E5B9
|
||||||
|
z = (z ^ (z >> 27)) &* 0x94D049BB133111EB
|
||||||
|
return z ^ (z >> 31)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func nextDouble() -> Double {
|
||||||
|
Double(next() >> 11) * 0x1.0p-53
|
||||||
|
}
|
||||||
|
}
|
||||||
63
Sources/EcgSynKit/Xoshiro256Plus.swift
Normal file
63
Sources/EcgSynKit/Xoshiro256Plus.swift
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum Xoshiro256: Equatable {
|
||||||
|
public typealias State = (UInt64, UInt64, UInt64, UInt64)
|
||||||
|
|
||||||
|
internal static var invalidState: State { (0, 0, 0, 0) }
|
||||||
|
|
||||||
|
internal static func isValid(state: State) -> Bool {
|
||||||
|
state != invalidState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
@inline(__always)
|
||||||
|
internal func rotl(_ x: UInt64, _ k: UInt64) -> UInt64 {
|
||||||
|
(x << k) | (x >> (64 &- k))
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Xoshiro256Plus: RandomNumberGenerator {
|
||||||
|
public typealias State = Xoshiro256.State
|
||||||
|
|
||||||
|
private var state: State
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
var generator = SystemRandomNumberGenerator()
|
||||||
|
self.init(seed: generator.next())
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(seed: UInt64) {
|
||||||
|
var generator = SplitMix64(state: seed)
|
||||||
|
var state = Xoshiro256.invalidState
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
state = (generator.next(), generator.next(), generator.next(), generator.next())
|
||||||
|
} while !Xoshiro256.isValid(state: state)
|
||||||
|
|
||||||
|
self.init(state: state)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(state: State) {
|
||||||
|
precondition(Xoshiro256.isValid(state: state), "The state must not be zero")
|
||||||
|
self.state = state
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func next() -> UInt64 {
|
||||||
|
let result = state.0 &+ state.3
|
||||||
|
let t = state.1 << 17
|
||||||
|
|
||||||
|
state.2 ^= state.0
|
||||||
|
state.3 ^= state.1
|
||||||
|
state.1 ^= state.2
|
||||||
|
state.0 ^= state.3
|
||||||
|
|
||||||
|
state.2 ^= t
|
||||||
|
state.3 = rotl(state.3, 45)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func nextDouble() -> Double {
|
||||||
|
Float64(next() >> 11) * 0x1.0p-53
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user