Added functions for generating uniform/normal distributed randomness (#154)
Added functions for generating uniform/normal distributed randomness
This commit is contained in:
parent
4c3a462741
commit
d2318c4c34
|
@ -16,7 +16,6 @@ opt_in_rules:
|
|||
- empty_count
|
||||
- explicit_enum_raw_value
|
||||
- explicit_init
|
||||
- extension_access_modifier
|
||||
- fatal_error_message
|
||||
- file_header
|
||||
- first_where
|
||||
|
|
|
@ -649,7 +649,7 @@ func powInPlace<L>(_ lhs: inout L, _ rhs: Double) where L: UnsafeMutableMemoryAc
|
|||
return powInPlace(&lhs, rhs)
|
||||
}
|
||||
|
||||
//// MARK: - Square
|
||||
// MARK: - Square
|
||||
|
||||
public func sq<L>(_ lhs: L) -> [Float] where L: UnsafeMemoryAccessible, L.Element == Float {
|
||||
return withArray(from: lhs) { sqInPlace(&$0) }
|
||||
|
|
|
@ -124,7 +124,149 @@ public struct Matrix<Scalar> where Scalar: FloatingPoint, Scalar: ExpressibleByF
|
|||
|
||||
return matrix
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Initialization: Randomized
|
||||
|
||||
extension Matrix where Scalar == Float {
|
||||
/// Generates a matrix of uniform-distributed random values within a (closed) `range`.
|
||||
public static func random(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
in range: ClosedRange<Float> = 0.0...1.0
|
||||
) -> Matrix {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.random(
|
||||
rows: rows,
|
||||
columns: columns,
|
||||
in: range,
|
||||
using: &generator
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates a matrix of uniform-distributed random values within
|
||||
/// a (closed) `range`, based on the provided random-number `generator`.
|
||||
public static func random<T>(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
in range: ClosedRange<Float> = 0.0...1.0,
|
||||
using generator: inout T
|
||||
) -> Matrix where T: RandomNumberGenerator {
|
||||
let grid = Surge.random(
|
||||
count: rows * columns,
|
||||
in: range,
|
||||
using: &generator
|
||||
)
|
||||
return Matrix(rows: rows, columns: columns, grid: grid)
|
||||
}
|
||||
|
||||
/// Generates a matrix of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public static func randomNormal(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0
|
||||
) -> Matrix {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.randomNormal(
|
||||
rows: rows,
|
||||
columns: columns,
|
||||
mu: mu,
|
||||
sigma: sigma,
|
||||
using: &generator
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates a matrix of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public static func randomNormal<T>(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0,
|
||||
using generator: inout T
|
||||
) -> Matrix where T: RandomNumberGenerator {
|
||||
let grid = Surge.randomNormal(
|
||||
count: rows * columns,
|
||||
mu: mu,
|
||||
sigma: sigma,
|
||||
using: &generator
|
||||
)
|
||||
return Matrix(rows: rows, columns: columns, grid: grid)
|
||||
}
|
||||
}
|
||||
|
||||
extension Matrix where Scalar == Double {
|
||||
/// Generates a matrix of uniform-distributed random values within a (closed) `range`.
|
||||
public static func random(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
in range: ClosedRange<Double> = 0.0...1.0
|
||||
) -> Matrix {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.random(
|
||||
rows: rows,
|
||||
columns: columns,
|
||||
in: range,
|
||||
using: &generator
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates a matrix of uniform-distributed random values within
|
||||
/// a (closed) `range`, based on the provided random-number `generator`.
|
||||
public static func random<T>(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
in range: ClosedRange<Double> = 0.0...1.0,
|
||||
using generator: inout T
|
||||
) -> Matrix where T: RandomNumberGenerator {
|
||||
let grid = Surge.random(
|
||||
count: rows * columns,
|
||||
in: range,
|
||||
using: &generator
|
||||
)
|
||||
return Matrix(rows: rows, columns: columns, grid: grid)
|
||||
}
|
||||
|
||||
/// Generates a matrix of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public static func randomNormal(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0
|
||||
) -> Matrix {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.randomNormal(
|
||||
rows: rows,
|
||||
columns: columns,
|
||||
mu: mu,
|
||||
sigma: sigma,
|
||||
using: &generator
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates a matrix of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public static func randomNormal<T>(
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0,
|
||||
using generator: inout T
|
||||
) -> Matrix where T: RandomNumberGenerator {
|
||||
let grid = Surge.randomNormal(
|
||||
count: rows * columns,
|
||||
mu: mu,
|
||||
sigma: sigma,
|
||||
using: &generator
|
||||
)
|
||||
return Matrix(rows: rows, columns: columns, grid: grid)
|
||||
}
|
||||
}
|
||||
|
||||
extension Matrix {
|
||||
// MARK: - Subscript
|
||||
|
||||
public subscript(row: Int, column: Int) -> Scalar {
|
||||
|
|
|
@ -83,3 +83,61 @@ public func * (lhs: Float, rhs: Matrix<Float>) -> Matrix<Float> {
|
|||
public func * (lhs: Double, rhs: Matrix<Double>) -> Matrix<Double> {
|
||||
return mul(lhs, rhs)
|
||||
}
|
||||
|
||||
extension Float {
|
||||
/// Generates a normal-distributed random value with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public static func randomNormal(
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0
|
||||
) -> Float {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return randomNormal(mu: mu, sigma: sigma, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates a normal-distributed random value with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public static func randomNormal<T>(
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0,
|
||||
using generator: inout T
|
||||
) -> Float where T: RandomNumberGenerator {
|
||||
let lhs = Float.random(in: 0.0...1.0, using: &generator)
|
||||
let rhs = Float.random(in: 0.0...1.0, using: &generator)
|
||||
|
||||
let z = sqrt(-2.0 * log(lhs)) * cos(2.0 * .pi * rhs)
|
||||
|
||||
// After applying the transform `z` holds values with a sigma of `1.0` and a mu of `0.0`.
|
||||
|
||||
return z * sigma + mu
|
||||
}
|
||||
}
|
||||
|
||||
extension Double {
|
||||
/// Generates a normal-distributed random value with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public static func randomNormal(
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0
|
||||
) -> Double {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return randomNormal(mu: mu, sigma: sigma, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates a normal-distributed random value with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public static func randomNormal<T>(
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0,
|
||||
using generator: inout T
|
||||
) -> Double where T: RandomNumberGenerator {
|
||||
let lhs = Double.random(in: 0.0...1.0, using: &generator)
|
||||
let rhs = Double.random(in: 0.0...1.0, using: &generator)
|
||||
|
||||
let z = sqrt(-2.0 * log(lhs)) * cos(2.0 * .pi * rhs)
|
||||
|
||||
// After applying the transform `z` holds values with a sigma of `1.0` and a mu of `0.0`.
|
||||
|
||||
return z * sigma + mu
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,10 @@ public struct Vector<Scalar> where Scalar: FloatingPoint, Scalar: ExpressibleByF
|
|||
} else {
|
||||
scalars = Array(contents)
|
||||
}
|
||||
self.init(scalars: scalars)
|
||||
}
|
||||
|
||||
public init(scalars: [Scalar]) {
|
||||
self.dimensions = scalars.count
|
||||
self.scalars = scalars
|
||||
}
|
||||
|
@ -59,6 +63,98 @@ public struct Vector<Scalar> where Scalar: FloatingPoint, Scalar: ExpressibleByF
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - Initialization: Randomized
|
||||
|
||||
extension Vector where Scalar == Float {
|
||||
/// Generates a vector of uniform-distributed random values within a (closed) `range`.
|
||||
public static func random(
|
||||
count: Int,
|
||||
in range: ClosedRange<Float> = 0.0...1.0
|
||||
) -> Vector {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.random(count: count, in: range, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates a vector of uniform-distributed random values within
|
||||
/// a (closed) `range`, based on the provided random-number `generator`.
|
||||
public static func random<T>(
|
||||
count: Int,
|
||||
in range: ClosedRange<Float> = 0.0...1.0,
|
||||
using generator: inout T
|
||||
) -> Vector where T: RandomNumberGenerator {
|
||||
let scalars = Surge.random(count: count, in: range, using: &generator)
|
||||
return Vector(scalars: scalars)
|
||||
}
|
||||
|
||||
/// Generates a vector of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public static func randomNormal(
|
||||
count: Int,
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0
|
||||
) -> Vector {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.randomNormal(count: count, mu: mu, sigma: sigma, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates a vector of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public static func randomNormal<T>(
|
||||
count: Int,
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0,
|
||||
using generator: inout T
|
||||
) -> Vector where T: RandomNumberGenerator {
|
||||
let scalars = Surge.randomNormal(count: count, mu: mu, sigma: sigma, using: &generator)
|
||||
return Vector(scalars: scalars)
|
||||
}
|
||||
}
|
||||
|
||||
extension Vector where Scalar == Double {
|
||||
/// Generates a vector of uniform-distributed random values within a (closed) `range`.
|
||||
public static func random(
|
||||
count: Int,
|
||||
in range: ClosedRange<Double> = 0.0...1.0
|
||||
) -> Vector {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.random(count: count, in: range, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates a vector of uniform-distributed random values within
|
||||
/// a (closed) `range`, based on the provided random-number `generator`.
|
||||
public static func random<T>(
|
||||
count: Int,
|
||||
in range: ClosedRange<Double> = 0.0...1.0,
|
||||
using generator: inout T
|
||||
) -> Vector where T: RandomNumberGenerator {
|
||||
let scalars = Surge.random(count: count, in: range, using: &generator)
|
||||
return Vector(scalars: scalars)
|
||||
}
|
||||
|
||||
/// Generates a vector of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public static func randomNormal(
|
||||
count: Int,
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0
|
||||
) -> Vector {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return self.randomNormal(count: count, mu: mu, sigma: sigma, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates a vector of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public static func randomNormal<T>(
|
||||
count: Int,
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0,
|
||||
using generator: inout T
|
||||
) -> Vector where T: RandomNumberGenerator {
|
||||
let scalars = Surge.randomNormal(count: count, mu: mu, sigma: sigma, using: &generator)
|
||||
return Vector(scalars: scalars)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ExpressibleByArrayLiteral
|
||||
|
||||
extension Vector: ExpressibleByArrayLiteral {
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
// Copyright © 2014-2019 the Surge contributors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - Random: Uniform Distribution
|
||||
|
||||
/// Generates an array of uniform-distributed random values within a (closed) `range`.
|
||||
public func random(
|
||||
count: Int,
|
||||
in range: ClosedRange<Float> = 0.0...1.0
|
||||
) -> [Float] {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return random(count: count, in: range, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates an array of uniform-distributed random values within a (closed) `range`.
|
||||
public func random(
|
||||
count: Int,
|
||||
in range: ClosedRange<Double> = 0.0...1.0
|
||||
) -> [Double] {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return random(count: count, in: range, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates an array of uniform-distributed random values within a
|
||||
/// (closed) `range` based on the provided random-number `generator`.
|
||||
public func random<T>(
|
||||
count: Int,
|
||||
in range: ClosedRange<Float>,
|
||||
using generator: inout T
|
||||
) -> [Float] where T: RandomNumberGenerator {
|
||||
return (0..<count).map { _ in Float.random(in: range, using: &generator) }
|
||||
}
|
||||
|
||||
/// Generates an array of uniform-distributed random values within a
|
||||
/// (closed) `range` based on the provided random-number `generator`.
|
||||
public func random<T>(
|
||||
count: Int,
|
||||
in range: ClosedRange<Double>,
|
||||
using generator: inout T
|
||||
) -> [Double] where T: RandomNumberGenerator {
|
||||
return (0..<count).map { _ in Double.random(in: range, using: &generator) }
|
||||
}
|
||||
|
||||
/// Generates an array of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public func randomNormal(
|
||||
count: Int,
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0
|
||||
) -> [Float] {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return randomNormal(count: count, mu: mu, sigma: sigma, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates an array of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation).
|
||||
public func randomNormal(
|
||||
count: Int,
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0
|
||||
) -> [Double] {
|
||||
var generator = SystemRandomNumberGenerator()
|
||||
return randomNormal(count: count, mu: mu, sigma: sigma, using: &generator)
|
||||
}
|
||||
|
||||
/// Generates an array of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public func randomNormal<T>(
|
||||
count: Int,
|
||||
mu: Float = 0.0,
|
||||
sigma: Float = 1.0,
|
||||
using generator: inout T
|
||||
) -> [Float] where T: RandomNumberGenerator {
|
||||
var lhs: [Float] = random(count: count, in: 0.0...1.0, using: &generator)
|
||||
var rhs: [Float] = random(count: count, in: 0.0...1.0, using: &generator)
|
||||
|
||||
boxMullerTransformInPlace(&lhs, &rhs)
|
||||
|
||||
// After applying the transform `lhs` holds values with a sigma of `1.0` and a mu of `0.0`.
|
||||
|
||||
// stdNormal * sigma + mu
|
||||
mulInPlace(&lhs, sigma)
|
||||
addInPlace(&lhs, mu)
|
||||
|
||||
return lhs
|
||||
}
|
||||
|
||||
/// Generates an array of normal-distributed random values with given
|
||||
/// `mu` (mean) and `sigma` (std deviation) based on the provided random-number `generator`.
|
||||
public func randomNormal<T>(
|
||||
count: Int,
|
||||
mu: Double = 0.0,
|
||||
sigma: Double = 1.0,
|
||||
using generator: inout T
|
||||
) -> [Double] where T: RandomNumberGenerator {
|
||||
// Box-Muller transform
|
||||
|
||||
var lhs: [Double] = random(count: count, in: 0.0...1.0, using: &generator)
|
||||
var rhs: [Double] = random(count: count, in: 0.0...1.0, using: &generator)
|
||||
|
||||
boxMullerTransformInPlace(&lhs, &rhs)
|
||||
|
||||
// After applying the transform `lhs` holds values with a sigma of `1.0` and a mu of `0.0`.
|
||||
|
||||
// stdNormal * sigma + mu
|
||||
mulInPlace(&lhs, sigma)
|
||||
addInPlace(&lhs, mu)
|
||||
|
||||
return lhs
|
||||
}
|
||||
|
||||
/// Performs the Box-Muller transform in-place.
|
||||
///
|
||||
/// - Note:
|
||||
/// Upon return `lhs` will contain the result of the transform,
|
||||
/// while `rhs` will will contain discardable, undefined content.
|
||||
internal func boxMullerTransformInPlace<L, R>(
|
||||
_ lhs: inout L,
|
||||
_ rhs: inout R
|
||||
) where L: UnsafeMutableMemoryAccessible, R: UnsafeMutableMemoryAccessible, L.Element == Float, R.Element == Float {
|
||||
// Semantically this function calculates the following formula,
|
||||
// implementing to the Box-Muller transform:
|
||||
//
|
||||
// ```
|
||||
// return sqrt(-2.0 * log(lhs)) .* cos(2.0 * .pi * rhs)
|
||||
// ```
|
||||
//
|
||||
// But instead of creating (and shortly later disposing) a temporary array
|
||||
// on every partial expression we perform them efficiently in-place,
|
||||
// allocating and re-using nothing but the initial buffers `u1` and `u2`:
|
||||
//
|
||||
// The in-place operations correspond to above formula like this:
|
||||
//
|
||||
// ┌─2─────────────────┐
|
||||
// │ ┌─1───────────┐│
|
||||
// │ │ ┌─0────┐│
|
||||
// sqrt(-2.0 * log(lhs)) .* cos(2.0 * .pi * rhs)
|
||||
// │ └─3───────────┘│
|
||||
// │ └─4────────────────┘
|
||||
// └─5─────────────────────────────────────────┘
|
||||
|
||||
logInPlace(&lhs) // 0
|
||||
mulInPlace(&lhs, -2.0) // 1
|
||||
sqrtInPlace(&lhs) // 2
|
||||
|
||||
mulInPlace(&rhs, 2.0 * .pi) // 3
|
||||
cosInPlace(&rhs) // 4
|
||||
|
||||
elmulInPlace(&lhs, rhs) // 5
|
||||
}
|
||||
|
||||
/// Performs the Box-Muller transform in-place.
|
||||
///
|
||||
/// - Note:
|
||||
/// Upon return `lhs` will contain the result of the transform,
|
||||
/// while `rhs` will will contain discardable, undefined content.
|
||||
internal func boxMullerTransformInPlace<L, R>(
|
||||
_ lhs: inout L,
|
||||
_ rhs: inout R
|
||||
) where L: UnsafeMutableMemoryAccessible, R: UnsafeMutableMemoryAccessible, L.Element == Double, R.Element == Double {
|
||||
// Semantically this function calculates the following formula,
|
||||
// implementing to the Box-Muller transform:
|
||||
//
|
||||
// ```
|
||||
// return sqrt(-2.0 * log(lhs)) .* cos(2.0 * .pi * rhs)
|
||||
// ```
|
||||
//
|
||||
// But instead of creating (and shortly later disposing) a temporary array
|
||||
// on every partial expression we perform them efficiently in-place,
|
||||
// allocating and re-using nothing but the initial buffers `u1` and `u2`:
|
||||
//
|
||||
// The in-place operations correspond to above formula like this:
|
||||
//
|
||||
// ┌─2─────────────────┐
|
||||
// │ ┌─1───────────┐│
|
||||
// │ │ ┌─0────┐│
|
||||
// sqrt(-2.0 * log(lhs)) .* cos(2.0 * .pi * rhs)
|
||||
// │ └─3───────────┘│
|
||||
// │ └─4────────────────┘
|
||||
// └─5─────────────────────────────────────────┘
|
||||
|
||||
logInPlace(&lhs) // 0
|
||||
mulInPlace(&lhs, -2.0) // 1
|
||||
sqrtInPlace(&lhs) // 2
|
||||
|
||||
mulInPlace(&rhs, 2.0 * .pi) // 3
|
||||
cosInPlace(&rhs) // 4
|
||||
|
||||
elmulInPlace(&lhs, rhs) // 5
|
||||
}
|
|
@ -91,9 +91,16 @@
|
|||
CAAF500C233A7B6700CC0AA7 /* Surge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614AD31F1FC0AD99002BFE1C /* Surge.framework */; };
|
||||
CAAF5015233A7D4100CC0AA7 /* ArithmeticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */; };
|
||||
CAAF501A233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAAF5019233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift */; };
|
||||
CAD8E5BE2343D796001B172A /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5BD2343D796001B172A /* Random.swift */; };
|
||||
CAD8E5BF2343D884001B172A /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5BD2343D796001B172A /* Random.swift */; };
|
||||
CAD8E5C02343D885001B172A /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5BD2343D796001B172A /* Random.swift */; };
|
||||
CAD8E5C12343D885001B172A /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5BD2343D796001B172A /* Random.swift */; };
|
||||
CAD8E5CB2343FD38001B172A /* StatisticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5CA2343FD38001B172A /* StatisticsTests.swift */; };
|
||||
CAD8E5CC2343FD38001B172A /* StatisticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5CA2343FD38001B172A /* StatisticsTests.swift */; };
|
||||
CAD8E5CD2343FD38001B172A /* StatisticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5CA2343FD38001B172A /* StatisticsTests.swift */; };
|
||||
CAD8E5CF23441B33001B172A /* RandomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5CE23441B33001B172A /* RandomTests.swift */; };
|
||||
CAD8E5D023441B33001B172A /* RandomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5CE23441B33001B172A /* RandomTests.swift */; };
|
||||
CAD8E5D123441B33001B172A /* RandomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD8E5CE23441B33001B172A /* RandomTests.swift */; };
|
||||
CAEC79BF2319274F00516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; };
|
||||
CAEC79C02319275000516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; };
|
||||
CAEC79C12319275000516E10 /* OperatorPrecedences.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */; };
|
||||
|
@ -191,7 +198,9 @@
|
|||
CAAF500B233A7B6700CC0AA7 /* Info-BenchmarkTests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-BenchmarkTests.plist"; sourceTree = "<group>"; };
|
||||
CAAF5014233A7C7900CC0AA7 /* ArithmeticTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArithmeticTests.swift; sourceTree = "<group>"; };
|
||||
CAAF5019233A9E6300CC0AA7 /* SurgeBenchmarkTests+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SurgeBenchmarkTests+Extensions.swift"; sourceTree = "<group>"; };
|
||||
CAD8E5BD2343D796001B172A /* Random.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Random.swift; sourceTree = "<group>"; };
|
||||
CAD8E5CA2343FD38001B172A /* StatisticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatisticsTests.swift; sourceTree = "<group>"; };
|
||||
CAD8E5CE23441B33001B172A /* RandomTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomTests.swift; sourceTree = "<group>"; };
|
||||
CAEC79B72319244D00516E10 /* OperatorPrecedences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorPrecedences.swift; sourceTree = "<group>"; };
|
||||
CAEC79C323192FE300516E10 /* Scalar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scalar.swift; sourceTree = "<group>"; };
|
||||
CAEC79D12319343100516E10 /* Logarithm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logarithm.swift; sourceTree = "<group>"; };
|
||||
|
@ -287,6 +296,7 @@
|
|||
CAEC79CD2319338F00516E10 /* Linear Algebra */,
|
||||
CAEC79D02319343100516E10 /* Logarithm */,
|
||||
CAEC79CC2319337700516E10 /* Statistics */,
|
||||
CA874E39236894C900C485CB /* Random */,
|
||||
CAEC79CE231933D700516E10 /* Trigonometry */,
|
||||
CAEC79C8231932E900516E10 /* Utilities */,
|
||||
);
|
||||
|
@ -305,12 +315,21 @@
|
|||
CAFE5DAD22F9ED4900A34887 /* VectorTests.swift */,
|
||||
CAAF4FCF2338F09700CC0AA7 /* ScalarTests.swift */,
|
||||
CAD8E5CA2343FD38001B172A /* StatisticsTests.swift */,
|
||||
CAD8E5CE23441B33001B172A /* RandomTests.swift */,
|
||||
CAFE5DA422F9EC1D00A34887 /* XCTAssert+Surge.swift */,
|
||||
CA945C2C233ABC0D00D95127 /* SurgeTests+Extensions.swift */,
|
||||
);
|
||||
path = SurgeTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA874E39236894C900C485CB /* Random */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CAD8E5BD2343D796001B172A /* Random.swift */,
|
||||
);
|
||||
path = Random;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CAAF5008233A7B6700CC0AA7 /* SurgeBenchmarkTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -840,6 +859,7 @@
|
|||
614AD33E1FC0AF72002BFE1C /* Matrix.swift in Sources */,
|
||||
61E930C32070B69300694FCB /* UnsafeMutableMemory.swift in Sources */,
|
||||
61E930C92070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */,
|
||||
CAD8E5BF2343D884001B172A /* Random.swift in Sources */,
|
||||
CAEC79D32319343100516E10 /* Logarithm.swift in Sources */,
|
||||
614AD3391FC0AF72002BFE1C /* Auxiliary.swift in Sources */,
|
||||
614AD3411FC0AF72002BFE1C /* Trigonometric.swift in Sources */,
|
||||
|
@ -860,6 +880,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CAD8E5D023441B33001B172A /* RandomTests.swift in Sources */,
|
||||
CAAF5001233A701A00CC0AA7 /* LogarithmTests.swift in Sources */,
|
||||
614AD3481FC0AF77002BFE1C /* MatrixTests.swift in Sources */,
|
||||
CAAF4FFD2339651700CC0AA7 /* ScalarTests.swift in Sources */,
|
||||
|
@ -881,6 +902,7 @@
|
|||
614AD36F1FC0B0CC002BFE1C /* Matrix.swift in Sources */,
|
||||
61E930C42070B69300694FCB /* UnsafeMutableMemory.swift in Sources */,
|
||||
61E930CA2070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */,
|
||||
CAD8E5C02343D885001B172A /* Random.swift in Sources */,
|
||||
CAEC79D42319343100516E10 /* Logarithm.swift in Sources */,
|
||||
614AD36A1FC0B0CC002BFE1C /* Auxiliary.swift in Sources */,
|
||||
614AD3721FC0B0CC002BFE1C /* Trigonometric.swift in Sources */,
|
||||
|
@ -901,6 +923,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CAD8E5D123441B33001B172A /* RandomTests.swift in Sources */,
|
||||
CAAF5002233A701A00CC0AA7 /* LogarithmTests.swift in Sources */,
|
||||
614AD3791FC0B0D2002BFE1C /* MatrixTests.swift in Sources */,
|
||||
CAAF4FFE2339651800CC0AA7 /* ScalarTests.swift in Sources */,
|
||||
|
@ -922,6 +945,7 @@
|
|||
614AD3911FC0B134002BFE1C /* Matrix.swift in Sources */,
|
||||
61E930C52070B69300694FCB /* UnsafeMutableMemory.swift in Sources */,
|
||||
61E930CB2070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */,
|
||||
CAD8E5C12343D885001B172A /* Random.swift in Sources */,
|
||||
CAEC79D52319343100516E10 /* Logarithm.swift in Sources */,
|
||||
614AD38C1FC0B134002BFE1C /* Auxiliary.swift in Sources */,
|
||||
614AD3941FC0B134002BFE1C /* Trigonometric.swift in Sources */,
|
||||
|
@ -954,6 +978,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CAD8E5CF23441B33001B172A /* RandomTests.swift in Sources */,
|
||||
CAAF5000233A701A00CC0AA7 /* LogarithmTests.swift in Sources */,
|
||||
61A0AD7B1F70D22600B99FFB /* MatrixTests.swift in Sources */,
|
||||
CAAF4FFC2339651600CC0AA7 /* ScalarTests.swift in Sources */,
|
||||
|
@ -975,6 +1000,7 @@
|
|||
6153945C1F762B59002A4AD2 /* Matrix.swift in Sources */,
|
||||
61E930C22070B69300694FCB /* UnsafeMutableMemory.swift in Sources */,
|
||||
61E930C82070BCCD00694FCB /* ArraySlice+Extensions.swift in Sources */,
|
||||
CAD8E5BE2343D796001B172A /* Random.swift in Sources */,
|
||||
CAEC79D22319343100516E10 /* Logarithm.swift in Sources */,
|
||||
615394571F762B59002A4AD2 /* Auxiliary.swift in Sources */,
|
||||
615394601F762B59002A4AD2 /* Trigonometric.swift in Sources */,
|
||||
|
|
|
@ -1037,9 +1037,9 @@ class MatrixTests: XCTestCase {
|
|||
guard a.count == b.count else {
|
||||
return false
|
||||
}
|
||||
return (zip(a, b).first { a, e -> Bool in
|
||||
return !zip(a, b).contains { a, e -> Bool in
|
||||
!(abs(a.0 - e.0) < accuracy && abs(a.1 - e.1) < accuracy)
|
||||
}) == nil
|
||||
}
|
||||
}
|
||||
|
||||
func eigen_decomposition_trivial_generic<T: FloatingPoint & ExpressibleByFloatLiteral>(defaultAccuracy: T, eigendecompostionFn: (Matrix<T>) throws -> MatrixEigenDecompositionResult<T>) throws {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright © 2014-2019 the Surge contributors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import Surge
|
||||
|
||||
// swiftlint:disable nesting
|
||||
|
||||
class RandomTests: XCTestCase {
|
||||
// MARK: - Box-Muller Transform
|
||||
|
||||
func test_box_muller_transform_float() {
|
||||
typealias Scalar = Float
|
||||
|
||||
let lhs: [Scalar] = .randomNormalized()
|
||||
let rhs: [Scalar] = .randomNormalized()
|
||||
|
||||
let actual: [Scalar] = { lhs, rhs in
|
||||
var (lhs, rhs) = (lhs, rhs)
|
||||
boxMullerTransformInPlace(&lhs, &rhs)
|
||||
return lhs
|
||||
}(lhs, rhs)
|
||||
|
||||
let expected: [Scalar] = zip(lhs, rhs).map { args in
|
||||
let (lhs, rhs) = args
|
||||
return sqrt(-2.0 * log(lhs)) * cos(2.0 * .pi * rhs)
|
||||
}
|
||||
|
||||
XCTAssertEqual(actual, expected, accuracy: 1e-4)
|
||||
}
|
||||
|
||||
func test_box_muller_transform_double() {
|
||||
typealias Scalar = Double
|
||||
|
||||
let lhs: [Scalar] = .randomNormalized()
|
||||
let rhs: [Scalar] = .randomNormalized()
|
||||
|
||||
let actual: [Scalar] = { lhs, rhs in
|
||||
var (lhs, rhs) = (lhs, rhs)
|
||||
boxMullerTransformInPlace(&lhs, &rhs)
|
||||
return lhs
|
||||
}(lhs, rhs)
|
||||
|
||||
let expected: [Scalar] = zip(lhs, rhs).map { args in
|
||||
let (lhs, rhs) = args
|
||||
return sqrt(-2.0 * log(lhs)) * cos(2.0 * .pi * rhs)
|
||||
}
|
||||
|
||||
XCTAssertEqual(actual, expected, accuracy: 1e-4)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue