RandomKit is a Swift framework that makes random data generation simple and easy.
- Installation
- Benchmark
- Usage
- Extra
- License
- Platforms:
- macOS 10.9+
- iOS 8.0+
- watchOS 2.0+
- tvOS 9.0+
- Linux
- Xcode 8.0
- Swift 3.0
RandomKit is possibly also compatible with FreeBSD, Android, and Windows (under Cygwin) but has not been tested for those platforms.
The Swift Package Manager is a decentralized dependency manager for Swift.
-
Add the project to your
Package.swift
.import PackageDescription let package = Package( name: "MyAwesomeProject", dependencies: [ .Package(url: "https://github.com/nvzqz/RandomKit.git", majorVersion: 4) ] )
-
Import the RandomKit module.
import RandomKit
CocoaPods is a centralized dependency manager for Objective-C and Swift. Go here to learn more.
-
Add the project to your Podfile.
use_frameworks! pod 'RandomKit', '~> 4.3.1'
If you want to be on the bleeding edge, replace the last line with:
pod 'RandomKit', :git => 'https://github.com/nvzqz/RandomKit.git'
-
Run
pod install
and open the.xcworkspace
file to launch Xcode. -
Import the RandomKit framework.
import RandomKit
Carthage is a decentralized dependency manager for Objective-C and Swift.
-
Add the project to your Cartfile.
github "nvzqz/RandomKit"
-
Run
carthage update
and follow the additional steps in order to add RandomKit to your project. -
Import the RandomKit framework.
import RandomKit
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
.
Try it out for yourself! Download the repo and open 'RandomKit.playground'.
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)
-
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.
- Because the symbols for the
-
DeviceRandom
- Reads from "/dev/random" or "/dev/urandom" as its source.
-
MersenneTwister
-
Xoroshiro
-
Xorshift
-
XorshiftStar
SeedableRandomGenerator
is for types that can be seeded with some associated
Seed
type.
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.
RandomKit is very protocol-oriented, which gives it the ability to be very flexible and modular.
A protocol for types that can generate random values using a RandomGenerator
.
A protocol for types that can generate optional random values within a range
using a RandomGenerator
.
Int.random(within: 0 ..< 0, using: &randomGenerator) // nil
A protocol for types that can generate random values within a closed range
using a RandomGenerator
.
Int.random(within: -100 ... 100, using: &randomGenerator) // -79
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:)
.
Int.random(to: 2, using: &randomGenerator) // Either 0 or 1
Int.random(to: 0, using: &randomGenerator) // Always 0
Int.random(to: 32, using: &randomGenerator) // 15
Int.random(to: -5, using: &randomGenerator) // -3
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 to
RandomThroughValue
.
A protocol for types whose elements can be shuffled.
// Array
[1, 2, 3, 4, 5].shuffled(using: &randomGenerator) // [3, 4, 1, 5, 2]
// Dictionary
["a": 1, "b": 2, "c": 3].shuffled(using: &randomGenerator) // ["a": 3, "b": 1, "c": 2]
The mutable counterpart of shuffled(using:)
is shuffle(using:)
.
For better Array
shuffling performance, consider shuffling in-place with
shuffle(using:)
.
Similar to Shuffleable
, except no element is ever in its initial position.
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.
Int.random(using: &randomGenerator) // An Int within Int.min and Int.max
Int.random(within: 10...20, using: &randomGenerator) // An Int within 10 and 20
To create a positive signed integer, use random(to:using:)
or random(through:using:)
.
Int.random(to: 1000, using: &randomGenerator) // 731
Int.random(through: 10, using: &randomGenerator) // 4
Signed integers can be created from any range, without danger of overflow.
Int.random(within: (.min + 1000)...(.max - 200), using: &randomGenerator) // 5698527899712144154
Generate a random floating point value from within a range or 0.0...1.0
by
default.
Double.random(using: &randomGenerator) // 0.9813615573117475
Double.random(within: -10...10, using: &randomGenerator) // -4.03042337718197
Float.random(within: -10...10, using: &randomGenerator) // 5.167088
Float80.random(within: -10...10, using: &randomGenerator) // -3.63204542399198874
All FloatingPoint
types can also conform to RandomWithinClosedRange
out-of-the-box.
Bool.random(using:)
has a 50/50 chance of being true
.
If you need different probability, there's also random(withWeight:using:)
,
which has 1 in weight
chance of being true
.
String
, Character
, and UnicodeScalar
generate values within " "..."~"
by
default.
String.random(ofLength: 10, using: &randomGenerator) // "}+[=Ng>$w1"
String.random(ofLength: 10, within: "A"..."z", using: &randomGenerator) // "poUtXJIbv["
Character.random(using: &randomGenerator) // "#"
Character.random(within: "A"..."z", using: &randomGenerator) // "s"
All types that conform to Sequence
and/or Collection
have a random
property that returns a random element, or nil
if the collection is empty.
["Bob", "Cindy", "May", "Charles", "Javier"].random(using: &randomGenerator) // "Charles"
"Hello".characters.random(using: &randomGenerator) // "e"
Even Foundation types that conform to either protocol get this property.
NSDictionary(dictionary: ["k1":"v1", "k2":"v2"]).random(using: &randomGenerator) // (k1, v1)
NSSet(array: ["First", "Second", "Third", "Fourth"]).random(using: &randomGenerator) // "Third"
An array of random values can be generated for types conforming to Random
with
init(randomCount:using:)
.
Similar initializers exist for all other Random-
protocols.
let randoms = Array<Int>(randomCount: 100, using: &randomGenerator) // [8845477344689834233, -957454203475087100, ...]
For types conforming to UnsafeRandom
, a faster alternative is init(unsafeRandomCount:using:)
.
This initializer fills the buffer directly rather than using random(using:)
.
let unsafeRandoms = Array<Int>(unsafeRandomCount: 100, using: &randomGenerator) // [759709806207883991, 4618491969012429761, ...]
A benchmark of generating 1000 random arrays of 10000 count:
Generator | Safe (seconds) | Unsafe (seconds) |
---|---|---|
Xoroshiro |
0.0948 | 0.0271 |
Xorshift |
0.1066 | 0.0568 |
XorshiftStar |
0.1028 | 0.0341 |
MersenneTwister |
0.1208 | 0.0432 |
ARC4Random |
1.0034 | 0.2416 |
DeviceRandom |
10.0906 | 5.3348 |
Note: Results may vary due to various factors.
This same benchmark can be run with:
./benchmark.sh --all-generators --array 10000 --count 1000
A random Date
can be generated between two Date
or TimeInterval
values.
The default random(using:)
function returns a Date
within Date.distantPast
and
Date.distantFuture
.
Date.random(using: &randomGenerator) // "Aug 28, 2006, 3:38 AM"
Date.random(within: Date.distantPast...Date(), using: &randomGenerator) // "Feb 7, 472, 5:40 AM"
The Decimal
type conforms to various Random-
protocols.
The random(using:)
function returns a Decimal
between 0 and 1 by default.
Decimal.random(using: &randomGenerator) // 0.87490000409886706715888973957833129437
Decimal.random(within: 0.0...10.0, using: &randomGenerator) // 6.5464639772070720738747790627821299859
A random number can be generated from within an integer or double range, or
0...100
by default.
NSNumber.random(using: &randomGenerator) // 79
NSNumber.random(within: -50...100, using: &randomGenerator) // -27
NSNumber.random(within: 100...200, using: &randomGenerator) // 149.6156950363926
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
Because CGFloat
conforms to FloatingPoint
, it conforms to
RandomWithinClosedRange
just like how Double
and Float
do.
CGFloat.random(using: &randomGenerator) // 0.699803650379181
CGFloat.random(within: 0...100, using: &randomGenerator) // 43.27969591675319
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}
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}
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}
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 extensions for Károly's BigInt library are available in RandomKitBigInt.
RandomKit and its assets are released under the MIT License. Assets
can be found in the assets
branch.