|
| 1 | +# Update Guide |
| 2 | + |
| 3 | +This guide gives a few more details than the [changelog], in particular giving |
| 4 | +guidance on how to use new features and migrate away from old ones. |
| 5 | + |
| 6 | +[changelog]: CHANGELOG.md |
| 7 | + |
| 8 | +## Rand 0.5 |
| 9 | + |
| 10 | +The 0.5 release has quite significant changes over the 0.4 release; as such, |
| 11 | +it may be worth reading through the following coverage of breaking changes. |
| 12 | +This release also contains many optimisations, which are not detailed below. |
| 13 | + |
| 14 | +### Crates |
| 15 | + |
| 16 | +We have a new crate: `rand-core`! This crate houses some important traits, |
| 17 | +`RngCore`, `BlockRngCore`, `SeedableRng` and `CryptoRng`, the error types, as |
| 18 | +well as two modules with helpers for implementations: `le` and `impls`. It is |
| 19 | +recommended that implementations of generators use the `rand-core` trait while |
| 20 | +other users use only the `rand` crate, which re-exports most parts of `rand-core`. |
| 21 | + |
| 22 | +The `rand_derive` crate has been deprecated due to very low usage and |
| 23 | +deprecation of `Rand`. |
| 24 | + |
| 25 | +### Features |
| 26 | + |
| 27 | +Several new Cargo feature flags have been added: |
| 28 | + |
| 29 | +- `alloc`, used without `std`, allows use of `Box` and `Vec` |
| 30 | +- `serde-1` adds serialisation support to some PRNGs |
| 31 | +- `log` adds logging in a few places (primarily to `OsRng` and `JitterRng`) |
| 32 | + |
| 33 | +### `Rng` and friends (core traits) |
| 34 | + |
| 35 | +`Rng` trait has been split into two traits, a "back end" `RngCore` (implemented |
| 36 | +by generators) and a "front end" `Rng` implementing all the convenient extension |
| 37 | +methods. |
| 38 | + |
| 39 | +Implementations of generators must `impl RngCore` instead. Usage of `rand-core` |
| 40 | +for implementations is encouraged; the `rand_core::{le, impls}` modules may |
| 41 | +prove useful. |
| 42 | + |
| 43 | +Users of `Rng` *who don't need to implement it* won't need to make so many |
| 44 | +changes; often users can forget about `RngCore` and only import `Rng`. Instead |
| 45 | +of `RngCore::next_u32()` / `next_u64()` users should prefer `Rng::gen()`, and |
| 46 | +instead of `RngCore::fill_bytes(dest)`, `Rng::fill(dest)` can be used. |
| 47 | + |
| 48 | +#### `Rng` / `RngCore` methods |
| 49 | + |
| 50 | +To allow error handling from fallible sources (e.g. `OsRng`), a new |
| 51 | +`RngCore::try_fill_bytes` method has been added; for example `EntropyRng` uses |
| 52 | +this mechanism to fall back to `JitterRng` if `OsRng` fails, and various |
| 53 | +handlers produce better error messages. |
| 54 | +As before, the other methods will panic on failure, but since these are usually |
| 55 | +used with algorithmic generators which are usually infallible, this is |
| 56 | +considered an appropriate compromise. |
| 57 | + |
| 58 | +A few methods from the old `Rng` have been removed or deprecated: |
| 59 | + |
| 60 | +- `next_f32` and `next_f64`; these are no longer implementable by generators; |
| 61 | + use `gen` instead |
| 62 | +- `gen_iter`; users may instead use standard iterators with closures: |
| 63 | + `::std::iter::repeat(()).map(|()| rng.gen())` |
| 64 | +- `gen_ascii_chars`; use `repeat` as above and `rng.sample(Alphanumeric)` |
| 65 | +- `gen_weighted_bool(n)`; use `gen_bool(1.0 / n)` instead |
| 66 | + |
| 67 | +`Rng` has a few new methods: |
| 68 | + |
| 69 | +- `sample(distr)` is a shortcut for `distr.sample(rng)` for any `Distribution` |
| 70 | +- `gen_bool(p)` generates a boolean with probability `p` of being true |
| 71 | +- `fill` and `try_fill`, corresponding to `fill_bytes` and `try_fill_bytes` |
| 72 | + respectively (i.e. the only difference is error handling); these can fill |
| 73 | + and integer slice / array directly, and provide better performance |
| 74 | + than `gen()` |
| 75 | + |
| 76 | +#### Constructing PRNGs |
| 77 | + |
| 78 | +##### New randomly-initialised PRNGs |
| 79 | + |
| 80 | +A new trait has been added: `NewRng`. This is automatically implemented for any |
| 81 | +type supporting `SeedableRng`, and provides construction from fresh, strong |
| 82 | +entropy: |
| 83 | + |
| 84 | +```rust |
| 85 | +use rand::{ChaChaRng, NewRng}; |
| 86 | + |
| 87 | +let mut rng = ChaChaRng::new(); |
| 88 | +``` |
| 89 | + |
| 90 | +##### Seeding PRNGs |
| 91 | + |
| 92 | +The `SeedableRng` trait has been modified to include the seed type via an |
| 93 | +associated type (`SeedableRng::Seed`) instead of a template parameter |
| 94 | +(`SeedableRng<Seed>`). Additionally, all PRNGs now seed from a byte-array |
| 95 | +(`[u8; N]` for some fixed N). This allows generic handling of PRNG seeding |
| 96 | +which was not previously possible. |
| 97 | + |
| 98 | +PRNGs are no longer constructed from other PRNGs via `Rand` support / `gen()`, |
| 99 | +but through `SeedableRng::from_rng`, which allows error handling and is |
| 100 | +intentionally explicit. |
| 101 | + |
| 102 | +`SeedableRng::reseed` has been removed since it has no utility over `from_seed` |
| 103 | +and its performance advantage is questionable. |
| 104 | + |
| 105 | +Implementations of `SeedableRng` may need to change their `Seed` type to a |
| 106 | +byte-array; this restriction has been made to ensure portable handling of |
| 107 | +Endianness. Helper functions are available in `rand_core::le` to read `u32` and |
| 108 | +`u64` values from byte arrays. |
| 109 | + |
| 110 | +#### Block-based PRNGs |
| 111 | + |
| 112 | +rand-core has a new helper trait, `BlockRngCore`, and implementation, |
| 113 | +`BlockRng`. These are for use by generators which generate a block of random |
| 114 | +data at a time instead of word-sized values. Using this trait and implementation |
| 115 | +has two advantages: optimised `RngCore` methods are provided, and the PRNG can |
| 116 | +be used with `ReseedingRng` with very low overhead. |
| 117 | + |
| 118 | +#### Cryptographic RNGs |
| 119 | + |
| 120 | +A new trait has been added: `CryptoRng`. This is purely a marker trait to |
| 121 | +indicate which generators should be suitable for cryptography, e.g. |
| 122 | +`fn foo<R: Rng + CryptoRng>(rng: &mut R)`. *Suitability for cryptographic |
| 123 | +use cannot be guaranteed.* |
| 124 | + |
| 125 | +### Error handling |
| 126 | + |
| 127 | +A new `Error` type has been added, designed explicitly for no-std compatibility, |
| 128 | +simplicity, and enough flexibility for our uses (carrying a `cause` when |
| 129 | +possible): |
| 130 | +```rust |
| 131 | +pub struct Error { |
| 132 | + pub kind: ErrorKind, |
| 133 | + pub msg: &'static str, |
| 134 | + // some fields omitted |
| 135 | +} |
| 136 | +``` |
| 137 | +The associated `ErrorKind` allows broad classification of errors into permanent, |
| 138 | +unexpected, transient and not-yet-ready kinds. |
| 139 | + |
| 140 | +The following use the new error type: |
| 141 | + |
| 142 | +- `RngCore::try_fill_bytes` |
| 143 | +- `Rng::try_fill` |
| 144 | +- `OsRng::new` |
| 145 | +- `jitter::new` |
| 146 | + |
| 147 | +### External generators |
| 148 | + |
| 149 | +We have a new generator, `EntropyRng`, which wraps `OsRng` and `JitterRng` |
| 150 | +(preferring to use the former, but falling back to the latter if necessary). |
| 151 | +This allows easy construction with fallback via `SeedableRng::from_rng`, |
| 152 | +e.g. `IsaacRng::from_rng(EntropyRng::new())?`. This is equivalent to using |
| 153 | +`NewRng` except for error handling. |
| 154 | + |
| 155 | +It is recommended to use `EntropyRng` over `OsRng` to avoid errors on platforms |
| 156 | +with broken system generator, but it should be noted that the `JitterRng` |
| 157 | +fallback is very slow. |
| 158 | + |
| 159 | +### PRNGs |
| 160 | + |
| 161 | +*Pseudo-Random Number Generators* (i.e. deterministic algorithmic generators) |
| 162 | +have had a few changes since 0.4, and are now housed in the `prng` module |
| 163 | +(old names remain temporarily available for compatibility; eventually these |
| 164 | +generators will likely be housed outside the `rand` crate). |
| 165 | + |
| 166 | +All PRNGs now do not implement `Copy` to prevent accidental copying of the |
| 167 | +generator's state (and thus repetitions of generated values). Explicit cloning |
| 168 | +via `Clone` is still available. All PRNGs now have a custom implementation of |
| 169 | +`Debug` which does not print any internal state; this helps avoid accidentally |
| 170 | +leaking cryptographic generator state in log files. External PRNG |
| 171 | +implementations are advised to follow this pattern (see also doc on `RngCore`). |
| 172 | + |
| 173 | +`SmallRng` has been added as a wrapper, currently around `XorShiftRng` (but |
| 174 | +likely another algorithm soon). This is for uses where small state and fast |
| 175 | +initialisation are important but cryptographic strength is not required. |
| 176 | +(Actual performance of generation varies by benchmark; dependending on usage |
| 177 | +this may or may not be the fastest algorithm, but will always be fast.) |
| 178 | + |
| 179 | +#### `ReseedingRng` |
| 180 | + |
| 181 | +The `ReseedingRng` wrapper has been signficantly altered to reduce overhead. |
| 182 | +Unfortunately the new `ReseedingRng` is not compatible with all RNGs, but only |
| 183 | +those using `BlockRngCore`. |
| 184 | + |
| 185 | +#### ISAAC PRNGs |
| 186 | + |
| 187 | +The `IsaacRng` and `Isaac64Rng` PRNGs now have an additional construction |
| 188 | +method: `new_from_u64(seed)`. 64 bits of state is insufficient for cryptography |
| 189 | +but may be of use in simulations and games. This will likely be superceeded by |
| 190 | +a method to construct any PRNG from any hashable object in the future. |
| 191 | + |
| 192 | +#### HC-128 |
| 193 | + |
| 194 | +This is a new cryptographic generator, selected as one of the "stream ciphers |
| 195 | +suitable for widespread adoption" by eSTREAM. This is now the default |
| 196 | +cryptographic generator, used by `StdRng` and `thread_rng()`. |
| 197 | + |
| 198 | +### Helper functions/traits |
| 199 | + |
| 200 | +The `Rand` trait has been deprecated. Instead, users are encouraged to use |
| 201 | +`Uniform` which is a real distribution and supports the same sampling as `Rand`. |
| 202 | +`Rng::gen()` now uses `Uniform` and should work exactly as before. |
| 203 | + |
| 204 | +The `random()` function has been removed; users may simply use |
| 205 | +`thread_rng().gen()` instead or may choose to cache |
| 206 | +`let mut rng = thread_rng();` locally, or even use a different generator. |
| 207 | + |
| 208 | +`weak_rng()` has been deprecated; use `SmallRng::new()` instead. |
| 209 | + |
| 210 | +### Distributions |
| 211 | + |
| 212 | +The `Sample` and `IndependentSample` traits have been replaced by a single |
| 213 | +trait, `Distribution`. This is largely equivalent to `IndependentSample`, but |
| 214 | +with `ind_sample` replaced by just `sample`. Support for mutable distributions |
| 215 | +has been dropped; although it appears there may be a few genuine uses, these |
| 216 | +are not used widely enough to justify the existance of two independent traits |
| 217 | +or of having to provide mutable access to a distribution object. Both `Sample` |
| 218 | +and `IndependentSample` are still available, but deprecated; they will be |
| 219 | +removed in a future release. |
| 220 | + |
| 221 | +`Distribution::sample` (as well as several other functions) can now be called |
| 222 | +directly on type-erased (unsized) RNGs. |
| 223 | + |
| 224 | +`RandSample` has been removed (see `Rand` deprecation and new `Uniform` |
| 225 | +distribution). |
| 226 | + |
| 227 | +The `Open01` and `Closed01` wrappers have been removed. `Rng::gen()` (via |
| 228 | +`Uniform`) now yields samples from `(0, 1)` for floats; i.e. the same as the old |
| 229 | +`Open01`. This is considered sufficient for most uses. If you require more |
| 230 | +precision, use the `HighPrecision01` distribution. |
| 231 | + |
| 232 | +#### Uniform distributions |
| 233 | + |
| 234 | +Three new distributions are available: |
| 235 | + |
| 236 | +- `Uniform` produces uniformly-distributed samples for many different types, |
| 237 | + and acts as a replacement for `Rand` |
| 238 | +- `HighPrecision01` generates floating-point numbers in the range `[0, 1)` |
| 239 | + (similar to `Uniform`) but with as much precision as the floating point |
| 240 | + format can represent |
| 241 | +- `Alphanumeric` samples `char`s from the ranges `a-z A-Z 0-9` |
| 242 | + |
| 243 | +##### Ranges |
| 244 | + |
| 245 | +The `Range` distribution has been heavily adapted, while remaining largely |
| 246 | +backwards compatible: |
| 247 | + |
| 248 | +- `Range::new(low, high)` remains (half open `[low, high)`) |
| 249 | +- `Range::new_inclusive(low, high)` has been added, including `high` in the sample range |
| 250 | +- `Range::sample_single(low, high, rng)` is a faster variant for single usage sampling from `[low, high)` |
| 251 | + |
| 252 | +`Range` can now be implemented for user-defined types; see the `RangeImpl` type. |
| 253 | +`SampleRange` has been adapted to suit the new `Range` model. |
| 254 | + |
| 255 | +#### Non-uniform distributions |
| 256 | + |
| 257 | +Two distributions have been added: |
| 258 | + |
| 259 | +- Poisson, modelling the number of events expected from a constant-rate |
| 260 | + source within a fixed time interval (e.g. nuclear decay) |
| 261 | +- Binomial, modelling the outcome of a fixed number of yes-no trials |
| 262 | + |
| 263 | +The sampling methods are based on those in "Numerical Recipes in C". |
| 264 | + |
| 265 | +##### Exponential and Normal distributions |
| 266 | + |
| 267 | +The main `Exp` and `Normal` distributions are unchanged, however the |
| 268 | +"standard" versions, `Exp1` and `StandardNormal` are no longer wrapper types, |
| 269 | +but full distributions. Instead of writing `let Exp1(x) = rng.gen();` you now |
| 270 | +write `let x = rng.sample(Exp1);`. |
0 commit comments