Skip to content

Commit 22c62c7

Browse files
committed
Refactor Random protocol and extensions
1 parent b3acdcc commit 22c62c7

File tree

6 files changed

+239
-245
lines changed

6 files changed

+239
-245
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
Double extension to conform to Random protocol.
3+
*/
4+
5+
import Accelerate
6+
7+
@_documentation(visibility: private)
8+
extension Double: Random {
9+
10+
public static func random(size: Int, seed: UInt64?) -> Vector<Double> {
11+
var vec = Vector<Double>(size: size)
12+
var rng = Wyrand(seed: seed)
13+
for i in 0..<size {
14+
vec[i] = rng.next()
15+
}
16+
return vec
17+
}
18+
19+
public static func random(rows: Int, columns: Int, seed: UInt64?) -> Matrix<Double> {
20+
var mat = Matrix<Double>(rows: rows, columns: columns)
21+
var rng = Wyrand(seed: seed)
22+
for i in 0..<rows {
23+
for j in 0..<columns {
24+
mat[i, j] = rng.next()
25+
}
26+
}
27+
return mat
28+
}
29+
30+
public static func random<G: RandomNumberGenerator>(size: Int, rng: inout G) -> Vector<Double> {
31+
var vec = Vector<Double>(size: size)
32+
for i in 0..<size {
33+
vec[i] = Double(rng.next() >> 11) * 0x1.0p-53
34+
}
35+
return vec
36+
}
37+
38+
public static func random<G: RandomNumberGenerator>(rows: Int, columns: Int, rng: inout G) -> Matrix<Double> {
39+
var mat = Matrix<Double>(rows: rows, columns: columns)
40+
for i in 0..<rows {
41+
for j in 0..<columns {
42+
mat[i, j] = Double(rng.next() >> 11) * 0x1.0p-53
43+
}
44+
}
45+
return mat
46+
}
47+
48+
public static func randomBNNS(
49+
size: Int, bounds: (Double, Double),
50+
seed: UInt64, buffer: UnsafeMutableBufferPointer<Double>
51+
) {
52+
fatalError("BNNS does not support doubles")
53+
}
54+
55+
public static func randomDist(size: Int, dist: Int) -> Vector<Double> {
56+
var idist = dist
57+
var num = size
58+
59+
// Must be between 0 and 4095, and iseed[3] must be odd
60+
// See https://netlib.org/lapack/explore-html/d5/dd2/group__larnv.html
61+
var iseed: [Int] = (0..<3).map { _ in Int.random(in: 1..<4095) }
62+
iseed += [2 * (Int.random(in: 1..<4095) / 2) + 1 ]
63+
64+
let vec = Vector<Double>(size: size)
65+
dlarnv_(&idist, &iseed, &num, vec.buffer.baseAddress)
66+
return vec
67+
}
68+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
Float extension to conform to Random protocol.
3+
*/
4+
5+
import Accelerate
6+
7+
@_documentation(visibility: private)
8+
extension Float: Random {
9+
10+
public static func random(size: Int, seed: UInt64?) -> Vector<Float> {
11+
var vec = Vector<Float>(size: size)
12+
var rng = Wyrand(seed: seed)
13+
for i in 0..<size {
14+
vec[i] = rng.next()
15+
}
16+
return vec
17+
}
18+
19+
public static func random(rows: Int, columns: Int, seed: UInt64?) -> Matrix<Float> {
20+
var mat = Matrix<Float>(rows: rows, columns: columns)
21+
var rng = Wyrand(seed: seed)
22+
for i in 0..<rows {
23+
for j in 0..<columns {
24+
mat[i, j] = rng.next()
25+
}
26+
}
27+
return mat
28+
}
29+
30+
public static func random<G: RandomNumberGenerator>(size: Int, rng: inout G) -> Vector<Float> {
31+
var vec = Vector<Float>(size: size)
32+
for i in 0..<size {
33+
vec[i] = Float(rng.next() >> 40) * 0x1.0p-24
34+
}
35+
return vec
36+
}
37+
38+
public static func random<G: RandomNumberGenerator>(rows: Int, columns: Int, rng: inout G) -> Matrix<Float> {
39+
var mat = Matrix<Float>(rows: rows, columns: columns)
40+
for i in 0..<rows {
41+
for j in 0..<columns {
42+
mat[i, j] = Float(rng.next() >> 40) * 0x1.0p-24
43+
}
44+
}
45+
return mat
46+
}
47+
48+
public static func randomBNNS(
49+
size: Int, bounds: (Float, Float),
50+
seed: UInt64, buffer: UnsafeMutableBufferPointer<Float>
51+
) {
52+
var desc = BNNSNDArrayDescriptor(data: buffer, shape: .vector(size))!
53+
let rng = BNNSCreateRandomGeneratorWithSeed(BNNSRandomGeneratorMethodAES_CTR, seed, nil)
54+
BNNSRandomFillUniformFloat(rng, &desc, bounds.0, bounds.1)
55+
}
56+
57+
public static func randomDist(size: Int, dist: Int) -> Vector<Float> {
58+
var idist = dist
59+
var num = size
60+
61+
// Must be between 0 and 4095, and iseed[3] must be odd
62+
// See https://netlib.org/lapack/explore-html/d5/dd2/group__larnv.html
63+
var iseed: [Int] = (0..<3).map { _ in Int.random(in: 1..<4095) }
64+
iseed += [2 * (Int.random(in: 1..<4095) / 2) + 1 ]
65+
66+
let vec = Vector<Float>(size: size)
67+
slarnv_(&idist, &iseed, &num, vec.buffer.baseAddress)
68+
return vec
69+
}
70+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
Matrix extension to conform to Random protocol.
3+
*/
4+
5+
extension Matrix where Scalar: Random {
6+
7+
/// Create a matrix of random values from a uniform distribution over [0, 1).
8+
/// ```swift
9+
/// let a = Matrix<Float>.random(2, 3)
10+
/// let b = Matrix<Double>.random(2, 2, seed: 123456)
11+
/// ```
12+
/// This method uses the ``Wyrand`` pseudorandom number generator (PRNG) to generate the random values in the
13+
/// matrix. The values are sampled from a uniform distribution [0, 1) which includes zero but excludes one. An
14+
/// optional seed can be provided for reproducible results.
15+
/// - Parameters:
16+
/// - rows: Number of matrix rows.
17+
/// - columns: Number of matrix columns.
18+
/// - seed: Seed for the Wyrand generator.
19+
/// - Returns: Matrix of random values.
20+
public static func random(_ rows: Int, _ columns: Int, seed: UInt64? = nil) -> Matrix {
21+
Scalar.random(rows: rows, columns: columns, seed: seed)
22+
}
23+
24+
/// Create a matrix of random values from a uniform distribution over [0, 1) using a random number generator.
25+
/// ```swift
26+
/// var rng = Xoroshiro128Plus(seed: (1227493545477, 7213431619994))
27+
/// let a = Matrix<Double>.random(5, 4, using: &rng)
28+
/// ```
29+
/// The example uses the ``Xoroshiro128Plus`` pseudorandom number generator (PRNG) to generate random values to
30+
/// fill the matrix. The generator is seeded with two integers otherwise random seeds are used if none are given.
31+
/// - Parameters:
32+
/// - rows: Number of matrix rows.
33+
/// - columns: Number of matrix columns.
34+
/// - rng: Random number generator.
35+
/// - Returns: Matrix of random values.
36+
public static func random<G: RandomNumberGenerator>(_ rows: Int, _ columns: Int, using rng: inout G) -> Matrix {
37+
Scalar.random(rows: rows, columns: columns, rng: &rng)
38+
}
39+
}
Lines changed: 1 addition & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
/*
22
Random protocol.
3-
Random extensions for Float and Double.
4-
Random extensions for Vector.
53
*/
64

75
import Accelerate
@@ -15,187 +13,5 @@ public protocol Random {
1513
static func random<G: RandomNumberGenerator>(rows: Int, columns: Int, rng: inout G) -> Matrix<Self>
1614

1715
static func randomBNNS(size: Int, bounds: (Self, Self), seed: UInt64, buffer: UnsafeMutableBufferPointer<Self>)
18-
}
19-
20-
@_documentation(visibility: private)
21-
extension Float: Random {
22-
23-
public static func random(size: Int, seed: UInt64?) -> Vector<Float> {
24-
var vec = Vector<Float>(size: size)
25-
var rng = Wyrand(seed: seed)
26-
for i in 0..<size {
27-
vec[i] = rng.next()
28-
}
29-
return vec
30-
}
31-
32-
public static func random(rows: Int, columns: Int, seed: UInt64?) -> Matrix<Float> {
33-
var mat = Matrix<Float>(rows: rows, columns: columns)
34-
var rng = Wyrand(seed: seed)
35-
for i in 0..<rows {
36-
for j in 0..<columns {
37-
mat[i, j] = rng.next()
38-
}
39-
}
40-
return mat
41-
}
42-
43-
public static func random<G: RandomNumberGenerator>(size: Int, rng: inout G) -> Vector<Float> {
44-
var vec = Vector<Float>(size: size)
45-
for i in 0..<size {
46-
vec[i] = Float(rng.next() >> 40) * 0x1.0p-24
47-
}
48-
return vec
49-
}
50-
51-
public static func random<G: RandomNumberGenerator>(rows: Int, columns: Int, rng: inout G) -> Matrix<Float> {
52-
var mat = Matrix<Float>(rows: rows, columns: columns)
53-
for i in 0..<rows {
54-
for j in 0..<columns {
55-
mat[i, j] = Float(rng.next() >> 40) * 0x1.0p-24
56-
}
57-
}
58-
return mat
59-
}
60-
61-
public static func randomBNNS(
62-
size: Int, bounds: (Float, Float),
63-
seed: UInt64, buffer: UnsafeMutableBufferPointer<Float>
64-
) {
65-
var desc = BNNSNDArrayDescriptor(data: buffer, shape: .vector(size))!
66-
let rng = BNNSCreateRandomGeneratorWithSeed(BNNSRandomGeneratorMethodAES_CTR, seed, nil)
67-
BNNSRandomFillUniformFloat(rng, &desc, bounds.0, bounds.1)
68-
}
69-
}
70-
71-
@_documentation(visibility: private)
72-
extension Double: Random {
73-
74-
public static func random(size: Int, seed: UInt64?) -> Vector<Double> {
75-
var vec = Vector<Double>(size: size)
76-
var rng = Wyrand(seed: seed)
77-
for i in 0..<size {
78-
vec[i] = rng.next()
79-
}
80-
return vec
81-
}
82-
83-
public static func random(rows: Int, columns: Int, seed: UInt64?) -> Matrix<Double> {
84-
var mat = Matrix<Double>(rows: rows, columns: columns)
85-
var rng = Wyrand(seed: seed)
86-
for i in 0..<rows {
87-
for j in 0..<columns {
88-
mat[i, j] = rng.next()
89-
}
90-
}
91-
return mat
92-
}
93-
94-
public static func random<G: RandomNumberGenerator>(size: Int, rng: inout G) -> Vector<Double> {
95-
var vec = Vector<Double>(size: size)
96-
for i in 0..<size {
97-
vec[i] = Double(rng.next() >> 11) * 0x1.0p-53
98-
}
99-
return vec
100-
}
101-
102-
public static func random<G: RandomNumberGenerator>(rows: Int, columns: Int, rng: inout G) -> Matrix<Double> {
103-
var mat = Matrix<Double>(rows: rows, columns: columns)
104-
for i in 0..<rows {
105-
for j in 0..<columns {
106-
mat[i, j] = Double(rng.next() >> 11) * 0x1.0p-53
107-
}
108-
}
109-
return mat
110-
}
111-
112-
public static func randomBNNS(
113-
size: Int, bounds: (Double, Double),
114-
seed: UInt64, buffer: UnsafeMutableBufferPointer<Double>
115-
) {
116-
fatalError("BNNS does not support doubles")
117-
}
118-
}
119-
120-
extension Vector where Scalar: Random {
121-
122-
/// Create a vector of random values from a uniform distribution over [0, 1).
123-
/// ```swift
124-
/// let a = Vector<Float>.random(5)
125-
/// let b = Vector<Double>.random(8, seed: 123456)
126-
/// ```
127-
/// This method uses the ``Wyrand`` pseudorandom number generator (PRNG) to generate the random values in the
128-
/// vector. The values are sampled from a uniform distribution [0, 1) which includes zero but excludes one. An
129-
/// optional seed can be provided for reproducible results.
130-
/// - Parameters:
131-
/// - size: Size of the vector.
132-
/// - seed: Seed for the Wyrand generator.
133-
/// - Returns: Vector of random values.
134-
public static func random(_ size: Int, seed: UInt64? = nil) -> Vector {
135-
Scalar.random(size: size, seed: seed)
136-
}
137-
138-
/// Create a vector of random values from a uniform distribution over [0, 1) using a random number generator.
139-
/// ```swift
140-
/// var rng = Xoroshiro128Plus(seed: (1227493545477, 7213431619994))
141-
/// let a = Vector<Float>.random(5, using: &rng)
142-
/// ```
143-
/// The example uses the ``Xoroshiro128Plus`` pseudorandom number generator (PRNG) to generate random values to
144-
/// fill the vector. The generator is seeded with two integers otherwise random seeds are used if none are given.
145-
/// - Parameters:
146-
/// - size: Size of the vector.
147-
/// - rng: Random number generator.
148-
/// - Returns: Vector or random values.
149-
public static func random<G: RandomNumberGenerator>(_ size: Int, using rng: inout G) -> Vector {
150-
Scalar.random(size: size, rng: &rng)
151-
}
152-
153-
/// Create a vector of random float values using BNNS.
154-
/// - Parameters:
155-
/// - size: Size of the vector.
156-
/// - bounds: The lower and upper bounds of the uniform random distribution.
157-
/// - seed: Seed for the random number generator.
158-
/// - Returns: Vector of random float values.
159-
public static func randomBNNS(size: Int, bounds: (Scalar, Scalar), seed: UInt64? = nil) -> Vector {
160-
let s = seed ?? UInt64.random(in: 0..<UInt64.max)
161-
let vec = Vector<Scalar>(size: size)
162-
Scalar.randomBNNS(size: size, bounds: bounds, seed: s, buffer: vec.buffer)
163-
return vec
164-
}
165-
}
166-
167-
extension Matrix where Scalar: Random {
168-
169-
/// Create a matrix of random values from a uniform distribution over [0, 1).
170-
/// ```swift
171-
/// let a = Matrix<Float>.random(2, 3)
172-
/// let b = Matrix<Double>.random(2, 2, seed: 123456)
173-
/// ```
174-
/// This method uses the ``Wyrand`` pseudorandom number generator (PRNG) to generate the random values in the
175-
/// matrix. The values are sampled from a uniform distribution [0, 1) which includes zero but excludes one. An
176-
/// optional seed can be provided for reproducible results.
177-
/// - Parameters:
178-
/// - rows: Number of matrix rows.
179-
/// - columns: Number of matrix columns.
180-
/// - seed: Seed for the Wyrand generator.
181-
/// - Returns: Matrix of random values.
182-
public static func random(_ rows: Int, _ columns: Int, seed: UInt64? = nil) -> Matrix {
183-
Scalar.random(rows: rows, columns: columns, seed: seed)
184-
}
185-
186-
/// Create a matrix of random values from a uniform distribution over [0, 1) using a random number generator.
187-
/// ```swift
188-
/// var rng = Xoroshiro128Plus(seed: (1227493545477, 7213431619994))
189-
/// let a = Matrix<Double>.random(5, 4, using: &rng)
190-
/// ```
191-
/// The example uses the ``Xoroshiro128Plus`` pseudorandom number generator (PRNG) to generate random values to
192-
/// fill the matrix. The generator is seeded with two integers otherwise random seeds are used if none are given.
193-
/// - Parameters:
194-
/// - rows: Number of matrix rows.
195-
/// - columns: Number of matrix columns.
196-
/// - rng: Random number generator.
197-
/// - Returns: Matrix of random values.
198-
public static func random<G: RandomNumberGenerator>(_ rows: Int, _ columns: Int, using rng: inout G) -> Matrix {
199-
Scalar.random(rows: rows, columns: columns, rng: &rng)
200-
}
16+
static func randomDist(size: Int, dist: Int) -> Vector<Self>
20117
}

0 commit comments

Comments
 (0)