Run carthage update and follow the additional steps
in order to add RandomKit to your project.
Import the RandomKit framework.
import RandomKit
Benchmark
Various components of RandomKit can be easily benchmarked by running benchmark.sh.
./benchmark.sh [FLAGS] [PROTOCOLS]
Use the --help flag for information regarding how to use it.
Note: The default count is 10000000, which is A LOT if using the --array flag.
This can be changed by passing an argument into --count or -c.
Usage
Try it out for yourself! Download the repo and open ‘RandomKit.playground’.
RandomGenerator
The RandomGenerator protocol defines basic methods for generating primitive
values and randomizing a buffer.
All provided types that conform to RandomGenerator have a static default
value that can be passed as an inout argument to generation functions.
let value = Int.random(using: &Xoroshiro.default)
Available Generators
ARC4Random
Because the symbols for the arc4random family of functions aren’t
exported with Foundation on Linux and other platforms, they’re dynamically
loaded at runtime.
DeviceRandom
Reads from “/dev/random” or “/dev/urandom” as its source.
MersenneTwister
Xoroshiro
Xorshift
XorshiftStar
ChaCha
SeedableRandomGenerator
SeedableRandomGenerator is for types that can be seeded with some associated
Seed type.
RandomBytesGenerator
The RandomBytesGenerator protocol is for types that specialize in generating a
specific type that fills up a number of bytes. For example, MersenneTwister
specializes in generating UInt64 while Xorshift generates UInt32 values.
Thread Safety
For single-threaded programs, it is safe to use a global generator instance such
as Xoroshiro.default as a source of randomness.
For multi-threaded programs, the thread-local instances should be used. This
allows for different threads to use their own separate random generators without
a shared mutable state.
In the following example, randomGenerator is unique to each thread.
let randomBytes = Xoroshiro.withThreadLocal { randomGenerator in
return [UInt8](randomCount: 1000, using: &randomGenerator)
}
Thread-local generators are deallocated upon thread exit, so there’s no need to
worry about cleanup.
It’s recommended to not call withThreadLocal(_:) or get the threadLocal
pointer each individual time it’s needed. Retrieving the thread-local instance
incurs avoidable overhead.
// Bad
let value = Int.random(using: &Xoroshiro.threadLocal.pointee)
array.shuffle(using: &Xoroshiro.threadLocal.pointee)
// Good
let threadLocal = Xoroshiro.threadLocal
let value = Int.random(using: &threadLocal.pointee)
array.shuffle(using: &threadLocal.pointee)
// Better
Xoroshiro.withThreadLocal { randomGenerator in
let value = Int.random(using: &randomGenerator)
array.shuffle(using: &randomGenerator)
}
As a shortcut, you can even apply a function directly as a parameter.
let value = Xoroshiro.withThreadLocal(Int.random)
Prior to v4.4.0,
thread safety could be achieved by instantiating a new seeded instance of a
given RandomGenerator type. The problem with this is that unnecessary seeding
occurs each time. With this, the generator is seeded once and can then be reused
at later points.
Shortcuts to the reseeding version of a generator are also available:
A protocol for types that can generate random values from a base value to
another value, noninclusive.
The base value for integers is 0. This means that calling random(to:using:) on
a negative value will yield a random negative value or zero whereas a positive
value will yield a random positive value or zero.
If value == randomBase, value will be returned for random(to:using:).
For types conforming to UnsafeRandom, a faster alternative is init(unsafeRandomCount:using:).
This initializer fills the buffer directly rather than using random(using:).
A random color can be generated, with or without random alpha.
NSColor.random(using: &randomGenerator) // r 0.694 g 0.506 b 0.309 a 1.0
NSColor.random(alpha: true, using: &randomGenerator) // r 0.859 g 0.57 b 0.409 a 0.047
UIColor.random(using: &randomGenerator) // r 0.488 g 0.805 b 0.679 a 1.0
UIColor.random(alpha: true, using: &randomGenerator) // r 0.444 g 0.121 b 0.602 a 0.085
CoreGraphics Types
CGFloat
Because CGFloat conforms to FloatingPoint, it conforms to
RandomInClosedRange just like how Double and Float do.
A random point can be generated from within ranges for x and y.
CGPoint.random(using: &randomGenerator) // {x 70.093 y 95.721}
CGPoint.random(xRange: 0...200, yRange: 0...10, using: &randomGenerator) // {x 73.795 y 0.991}
CGSize
A random size can be generated from within ranges for width and height.
CGSize.random(using: &randomGenerator) // {w 3.744 h 35.932}
CGSize.random(widthRange: 0...50, heightRange: 0...400, using: &randomGenerator) // {w 38.271 h 239.636}
CGRect
A random rectangle can be generated from within ranges for x, y, width, and
height.
CGRect.random(using: &randomGenerator) // {x 3.872 y 46.15 w 8.852 h 20.201}
CGRect.random(xRange: 0...50,
yRange: 0...100,
widthRange: 0...25,
heightRange: 0...10,
using: &randomGenerator) // {x 13.212 y 79.147 w 20.656 h 5.663}
CGVector
A random vector can be generated from within ranges for dx and dy.
CGVector.random(using: &randomGenerator) // {dx 13.992 dy 89.376}
CGVector.random(dxRange: 0...50, dyRange: 0...10, using: &randomGenerator) // {dx 35.224 dy 13.463}
RandomKit is a Swift framework that makes random data generation simple and easy.
Build Status
master
Installation
Compatibility
RandomKit is possibly also compatible with FreeBSD, Android, and Windows (under Cygwin) but has not been tested for those platforms.
Install Using Swift Package Manager
The Swift Package Manager is a decentralized dependency manager for Swift.
Add the project to your
Package.swift
.Import the RandomKit module.
Install Using CocoaPods
CocoaPods is a centralized dependency manager for Objective-C and Swift. Go here to learn more.
Add the project to your Podfile.
If you want to be on the bleeding edge, replace the last line with:
Run
pod install
and open the.xcworkspace
file to launch Xcode.Import the RandomKit framework.
Install Using Carthage
Carthage is a decentralized dependency manager for Objective-C and Swift.
Add the project to your Cartfile.
Run
carthage update
and follow the additional steps in order to add RandomKit to your project.Import the RandomKit framework.
Benchmark
Various components of RandomKit can be easily benchmarked by running
benchmark.sh
.Use the
--help
flag for information regarding how to use it.Note: The default count is 10000000, which is A LOT if using the
--array
flag. This can be changed by passing an argument into--count
or-c
.Usage
Try it out for yourself! Download the repo and open ‘RandomKit.playground’.
RandomGenerator
The
RandomGenerator
protocol defines basic methods for generating primitive values and randomizing a buffer.All provided types that conform to
RandomGenerator
have a staticdefault
value that can be passed as aninout
argument to generation functions.Available Generators
ARC4Random
arc4random
family of functions aren’t exported with Foundation on Linux and other platforms, they’re dynamically loaded at runtime.DeviceRandom
MersenneTwister
Xoroshiro
Xorshift
XorshiftStar
ChaCha
SeedableRandomGenerator
SeedableRandomGenerator
is for types that can be seeded with some associatedSeed
type.RandomBytesGenerator
The
RandomBytesGenerator
protocol is for types that specialize in generating a specific type that fills up a number of bytes. For example,MersenneTwister
specializes in generatingUInt64
whileXorshift
generatesUInt32
values.Thread Safety
For single-threaded programs, it is safe to use a global generator instance such as
Xoroshiro.default
as a source of randomness.For multi-threaded programs, the thread-local instances should be used. This allows for different threads to use their own separate random generators without a shared mutable state.
In the following example,
randomGenerator
is unique to each thread.Thread-local generators are deallocated upon thread exit, so there’s no need to worry about cleanup.
It’s recommended to not call
withThreadLocal(_:)
or get thethreadLocal
pointer each individual time it’s needed. Retrieving the thread-local instance incurs avoidable overhead.As a shortcut, you can even apply a function directly as a parameter.
Prior to v4.4.0, thread safety could be achieved by instantiating a new seeded instance of a given
RandomGenerator
type. The problem with this is that unnecessary seeding occurs each time. With this, the generator is seeded once and can then be reused at later points.Shortcuts to the reseeding version of a generator are also available:
Which is way better than writing:
Protocols
RandomKit is very protocol-oriented, which gives it the ability to be very flexible and modular.
Random
A protocol for types that can generate random values using a
RandomGenerator
.RandomInRange
A protocol for types that can generate optional random values within a range using a
RandomGenerator
.RandomInClosedRange
A protocol for types that can generate random values within a closed range using a
RandomGenerator
.RandomToValue
A protocol for types that can generate random values from a base value to another value, noninclusive.
The base value for integers is 0. This means that calling
random(to:using:)
on a negative value will yield a random negative value or zero whereas a positive value will yield a random positive value or zero.If
value
==randomBase
,value
will be returned forrandom(to:using:)
.RandomThroughValue
A protocol for types that can generate random values from a base value through another value, inclusive.
The same rules regarding the base value of
RandomToValue
apply toRandomThroughValue
.RandomRetrievable
A protocol for types whose instances can have random elements retrieved.
Some Foundation types like
NSArray
conform to this protocol.RandomRetrievableInRange
A protocol for types whose instances can have random elements retrieved from within a
Range<Index>
.Shuffleable
A protocol for types whose elements can be shuffled.
The mutable counterpart of
shuffled(using:)
isshuffle(using:)
.For better
Array
shuffling performance, consider shuffling in-place withshuffle(using:)
.UniqueShuffleable
Similar to
Shuffleable
, except no element is ever in its initial position.Swift Types
Integers
All of Swift’s native integer types conform to the
Random-
protocols.The
random(using:)
function creates an integer of any value. As a result, negative values can result for signed integers.To create a positive signed integer, use
random(to:using:)
orrandom(through:using:)
.Signed integers can be created from any range, without danger of overflow.
Floating Point Numbers
Generate a random floating point value from within a range or
0.0...1.0
by default.All
FloatingPoint
types can also conform toRandomInClosedRange
out-of-the-box.Bool
Bool.random(using:)
has a 50/50 chance of beingtrue
.If you need different probability, there’s also
random(withWeight:using:)
, which has 1 inweight
chance of beingtrue
.String, Character, and UnicodeScalar
String
,Character
, andUnicodeScalar
generate values within" "..."~"
by default.Arrays
An array of random values can be generated for types conforming to
Random
withinit(randomCount:using:)
.Similar initializers exist for all other
Random-
protocols.For types conforming to
UnsafeRandom
, a faster alternative isinit(unsafeRandomCount:using:)
. This initializer fills the buffer directly rather than usingrandom(using:)
.Arrays Benchmark
A benchmark of generating 1000 random
Int
arrays of 10000 count:Xoroshiro
Xorshift
XorshiftStar
ChaCha
MersenneTwister
ARC4Random
DeviceRandom
Note: Results may vary due to various factors.
This same benchmark can be run with:
Foundation Types
Date
A random
Date
can be generated between twoDate
orTimeInterval
values.The default
random(using:)
function returns aDate
withinDate.distantPast
andDate.distantFuture
.Decimal
The
Decimal
type conforms to variousRandom-
protocols.The
random(using:)
function returns aDecimal
between 0 and 1 by default.NSNumber
A random number can be generated from within an integer or double range, or
0...100
by default.Cocoa and UIKit Types
NSColor and UIColor
A random color can be generated, with or without random alpha.
CoreGraphics Types
CGFloat
Because
CGFloat
conforms toFloatingPoint
, it conforms toRandomInClosedRange
just like howDouble
andFloat
do.CGPoint
A random point can be generated from within ranges for x and y.
CGSize
A random size can be generated from within ranges for width and height.
CGRect
A random rectangle can be generated from within ranges for x, y, width, and height.
CGVector
A random vector can be generated from within ranges for dx and dy.
Extra
BigInt
RandomKit extensions for Károly’s BigInt library are available in RandomKitBigInt.
License
RandomKit and its assets are released under the MIT License. Assets can be found in the
assets
branch.Parts of this project utilize code written by Matt Gallagher and, in conjunction with the MIT License, are licensed with that found here.