[](https://github.com/nvzqz/RandomKit)
RandomKit is a Swift framework that makes random data generation simple and easy. - [Build Status](#build-status) - [Installation](#installation) - [Compatibility](#compatibility) - [Swift Package Manager](#install-using-swift-package-manager) - [CocoaPods](#install-using-cocoapods) - [Carthage](#install-using-carthage) - [Benchmark](#benchmark) - [Usage](#usage) - [RandomGenerator](#randomgenerator) - [Thread Safety](#thread-safety) - [Protocols](#protocols) - [Random](#random) - [RandomInRange](#randominrange) - [RandomInClosedRange](#randominclosedrange) - [RandomToValue](#randomtovalue) - [RandomThroughValue](#randomthroughvalue) - [RandomRetrievable](#randomretrievable) - [RandomRetrievableInRange](#randomretrievableinrange) - [Shuffleable](#shuffleable) - [UniqueShuffleable](#uniqueshuffleable) - [Swift Types](#swift-types) - [Integers](#integers) - [Floating Point Numbers](#floating-point-numbers) - [Bool](#bool) - [String, Character, and UnicodeScalar](#string-character-and-unicodescalar) - [Arrays](#arrays) - [Arrays Benchmark](#arrays-benchmark) - [Foundation Types](#foundation-types) - [Date](#date) - [Decimal](#decimal) - [NSNumber](#nsnumber) - [Cocoa and UIKit Types](#cocoa-and-uikit-types) - [NSColor and UIColor](#nscolor-and-uicolor) - [CoreGraphics Types](#coregraphics-types) - [CGFloat](#cgfloat) - [CGPoint](#cgpoint) - [CGSize](#cgsize) - [CGRect](#cgrect) - [CGVector](#cgvector) - [Extra](#extra) - [BigInt](#bigint) - [License](#license) ## Build Status | Branch | Status | | :-------: | :----: | | `master` | [](https://travis-ci.org/nvzqz/RandomKit) | ## Installation ### Compatibility - Platforms: - macOS 10.9+ - iOS 8.0+ - watchOS 2.0+ - tvOS 9.0+ - Linux - Xcode 8.0+ - Swift 3.0.2+ & 4.0 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](https://swift.org/package-manager/) is a decentralized dependency manager for Swift. 1. Add the project to your `Package.swift`. ```swift import PackageDescription let package = Package( name: "MyAwesomeProject", dependencies: [ .Package(url: "https://github.com/nvzqz/RandomKit.git", majorVersion: 5) ] ) ``` 2. Import the RandomKit module. ```swift import RandomKit ``` ### Install Using CocoaPods [CocoaPods](https://cocoapods.org/) is a centralized dependency manager for Objective-C and Swift. Go [here](https://guides.cocoapods.org/using/index.html) to learn more. 1. Add the project to your [Podfile](https://guides.cocoapods.org/using/the-podfile.html). ```ruby use_frameworks! pod 'RandomKit', '~> 5.2.3' ``` If you want to be on the bleeding edge, replace the last line with: ```ruby pod 'RandomKit', :git => 'https://github.com/nvzqz/RandomKit.git' ``` 2. Run `pod install` and open the `.xcworkspace` file to launch Xcode. 3. Import the RandomKit framework. ```swift import RandomKit ``` ### Install Using Carthage [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager for Objective-C and Swift. 1. Add the project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). ``` github "nvzqz/RandomKit" ``` 2. Run `carthage update` and follow [the additional steps](https://github.com/Carthage/Carthage#getting-started) in order to add RandomKit to your project. 3. Import the RandomKit framework. ```swift import RandomKit ``` ## Benchmark Various components of RandomKit can be easily benchmarked by running `benchmark.sh`. ```shell ./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. ```swift 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. ```swift 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. ```swift // 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. ```swift let value = Xoroshiro.withThreadLocal(Int.random) ``` Prior to [v4.4.0](https://github.com/nvzqz/RandomKit/releases/tag/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: ```swift Xoroshiro.withThreadLocalReseeding { ... } ``` Which is *way* better than writing: ```swift ReseedingRandomGenerator.withThreadLocal(createdWith: { Xoroshiro.reseeding }) { ... } ``` ### 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`. ```swift Int.random(in: 0 ..< 0, using: &randomGenerator) // nil ``` #### RandomInClosedRange A protocol for types that can generate random values within a closed range using a `RandomGenerator`. ```swift Int.random(in: -100 ... 100, using: &randomGenerator) // -79 ``` #### 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 for `random(to:using:)`. ```swift 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 ``` #### 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 to `RandomThroughValue`. #### RandomRetrievable A protocol for types whose instances can have random elements retrieved. ```swift ["Bob", "Cindy", "May", "Charles", "Javier"].random(using: &randomGenerator) // "Charles" "Hello".characters.random(using: &randomGenerator) // "e" ``` 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