Skip to content

Commit

Permalink
Merge pull request #28 from vks/update-0.8
Browse files Browse the repository at this point in the history
Updating guide for Rand 0.8
  • Loading branch information
dhardy committed Dec 18, 2020
2 parents 19cb74d + 5c83a3c commit 49a77a8
Showing 1 changed file with 185 additions and 0 deletions.
185 changes: 185 additions & 0 deletions src/update-0.8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Updating to 0.8

In the following, instructions are provided for porting your code from
`rand 0.7` and `rand_distr 0.2` to `rand 0.8` and `rand_distr 0.3`.

## Dependencies

Rand crates now require `rustc` version 1.36.0 or later.
This allowed us to remove some unsafe code and simplify the internal `cfg` logic.

The dependency on `getrandom` was bumped to version 0.2. While this does not
affect Rand's API, you may be affected by some of the breaking changes even if
you use `getrandom` only as a dependency:

- You may have to update the `getrandom` features you are using. The
following features are now available:
- `"rdrand"`: Use the RDRAND instruction on `no_std` `x86/x86_64`
targets.
- `"js"`: Use JavaScript calls on `wasm32-unknown-unknown`. This
replaces the `stdweb` and `wasm-bindgen` features, which are
removed.
- `"custom"`: Allows you to specify a custom implementation.
- Unsupported targets no longer compile. If you require the previous behavior
(panicking at runtime instead of failing to compile), you can use the
`custom` feature to provide a panicking implementation.
- Hermit, L4Re and UEFI are no longer officially supported. You can use the
`rdrand` feature on these platforms.
- The minimum supported Linux kernel version is now 2.6.32.

If you are using `getrandom`'s API directly, there are further breaking changes
that may affect you. See its
[changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md#020---2020-09-10).


## Core features

`ThreadRng` no longer implements `Copy`. This was necessary to fix a possible
use-after-free in its thread-local destructor. Any code relying on `ThreadRng`
being copied must be updated to use a mutable reference instead. For example,
```
let rng = thread_rng();
let a: u32 = Standard.sample(rng);
let b: u32 = Standard.sample(rng);
```
can be replaced with the following code:
```
let mut rng = thread_rng();
let a: u32 = Standard.sample(&mut rng);
let b: u32 = Standard.sample(&mut rng);
```

[`Rng::gen_range`] now takes a `Range` instead of two numbers. This requires
replacing `gen_range(a, b)` with `gen_range(a..b)` in code written for `rand
0.7`. We suggest to replace the regular expression
`gen_range\(([^,]*),\s*([^)]*)\)` with `gen_range(\1..\2)` (or
`gen_range($1..$2)` in some tools without support for backreferences).
Additionally, if `a` or `b` were a reference, explicit dereferencing may now be
required. Inclusive ranges are now supported: `gen_range(a, b + 1)` can be
replaced with `gen_range(a..=b)`.

The `AsByteSliceMut` trait was replaced with the [`Fill`] trait. This should
only affect code implementing `AsByteSliceMut` on user-defined types, so they
are supported by [`Rng::fill`] and [`Rng::try_fill`]. Now, the [`Fill`] trait
has to be implemented instead: Rather than providing a mutable byte slice, the
user-defined type must be filled with random data.

The entire [`rand::rngs::adapter`] module is now restricted to the `std` feature.
While this is technically a breaking change, it should only affect `no_std` code
using [`ReseedingRng`], which is unlikely to exist in the wild.

## PRNGs

These have seen only small changes, but noteworthy is:

- [`StdRng`] and [`ThreadRng`] now use the ChaCha12 instead of the ChaCha20
algorithm. This improves performance and is a value-breaking change for
[`StdRng`].
- [`SmallRng`] now uses the Xoshiro128++ and Xoshiro256++ algorithm on 32-bit
and 64-bit platforms respectively. This reduces correlations of random data
generated from similar seeds, improves performance and is a value-breaking
change.
- [`StdRng`], [`SmallRng`], and [`StepRng`] now implement `PartialEq` and `Eq`.

## Distributions

The most widely used distributions ([`Standard`] and [`Uniform`]), were not
significantly changed. Only the following distributions suffered breaking
changes:

- The [`Alphanumeric`] distribution now samples bytes instead of chars. This
more closely reflects the internally used type, but old code likely has to
be adapted to perform the conversion from `u8` to `char`. For example, with
Rand 0.7 you could write:
```
let chars: String = iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
.take(7)
.collect();
```
With Rand 0.8, this is equivalent to the following:
```
let chars: String = iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
.map(char::from)
.take(7)
.collect();
```
- The alternative implementation of [`WeightedIndex`] employing the alias
method was moved from `rand` to [`rand_distr::WeightedAliasIndex`]. The
alias method is faster for large sizes, but it suffers from a slow
initialization, making it less generally useful.
- [`rand_distr::Dirichlet`] now uses boxed slices internally instead of `Vec`.
Therefore, the weights are taken as a slice instead of a `Vec` as input.
For example, the following `rand_distr 0.2` code
```
Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap();
```
can be replaced with the following `rand_distr 0.3` code:
```
Dirichlet::new(&[1.0, 2.0, 3.0]).unwrap();
```
- [`rand_distr::Poisson`] does no longer support sampling `u64` values directly.
Old code may have to be updated to perform the conversion from `f64`
explicitly.
- The custom `Float` trait in `rand_distr` was replaced with
`num_traits::Float`. Any implementations of `Float` for user-defined types
have to be migrated. Thanks to the math functions from `num_traits::Float`,
`rand_distr` now supports `no_std`.

Additonally, there were some minor improvements:

- The treatment of rounding errors and NaN was improved for the
[`WeightedIndex`] distribution.
- The [`UniformInt`] and [`WeightedIndex`] distributions now support serialization
via the `serde1` feature.
- The [`rand_distr::Exp`] distribution now supports the `lambda = 0` parametrization.

We also added several distributions:

- [`rand_distr::WeightedAliasIndex`] (moved from the `rand` crate)
- [`rand_distr::InverseGaussian`]
- [`rand_distr::NormalInverseGaussian`]

The `nightly` feature no longer implies the `simd_support` feature. If you were
relying on this for SIMD support, you will have to use `simd_support` feature
directly.

## Sequences

Weighted sampling without replacement is now supported, see
[`rand::seq::index::sample_weighted`] and
[`SliceRandom::choose_multiple_weighted`].

There have been [value-breaking
changes](https://github.com/rust-random/rand/pull/1059) to
[`IteratorRandom::choose`], improving accuracy and performance. Furthermore,
[`IteratorRandom::choose_stable`] was added to provide an alternative that
sacrifices performance for independence of iterator size hints.


[`Fill`]: ../rand/rand/trait.Fill.html
[`Rng::gen_range`]: ../rand/rand/trait.Rng.html#method.gen_range
[`Rng::fill`]: ../rand/rand/trait.Rng.html#method.fill
[`Rng::try_fill`]: ../rand/rand/trait.Rng.html#method.try_fill
[`SmallRng`]: ../rand/rand/rngs/struct.SmallRng.html
[`StdRng`]: ../rand/rand/rngs/struct.StdRng.html
[`StepRng`]: ../rand/rand/rngs/struct.StepRng.html
[`ThreadRng`]: ../rand/rand/rngs/struct.ThreadRng.html
[`ReseedingRng`]: ../rand/rand/rngs/adapter/struct.ReseedingRng.html
[`Standard`]: ../rand/rand/distributions/struct.Standard.html
[`Uniform`]: ../rand/rand/distributions/struct.Uniform.html
[`UniformInt`]: ../rand/rand/distributions/struct.UniformInt.html
[`Alphanumeric`]: ../rand/rand/distributions/struct.Alphanumeric.html
[`WeightedIndex`]: ../rand/rand/distributions/struct.WeightedIndex.html
[`rand::rngs::adapter`]: ../rand/rand/rngs/adapter/index.html
[`rand::seq::index::sample_weighted`]: ../rand/rand/seq/index/fn.sample_weighted.html
[`SliceRandom::choose_multiple_weighted`]: ../rand/rand/seq/trait.SliceRandom.html#method.choose_multiple_weighted
[`IteratorRandom::choose`]: ../rand/rand/seq/trait.IteratorRandom.html#method.choose
[`IteratorRandom::choose_stable`]: ../rand/rand/seq/trait.IteratorRandom.html#method.choose_stable
[`rand_distr::WeightedAliasIndex`]: ../rand/rand_distr/struct.WeightedAliasIndex.html
[`rand_distr::InverseGaussian`]: ../rand/rand_distr/struct.InverseGaussian.html
[`rand_distr::NormalInverseGaussian`]: ../rand/rand_distr/struct.NormalInverseGaussian.html
[`rand_distr::Dirichlet`]: ../rand/rand_distr/struct.Dirichlet.html
[`rand_distr::Poisson`]: ../rand/rand_distr/struct.Poisson.html
[`rand_distr::Exp`]: ../rand/rand_distr/struct.Exp.html

0 comments on commit 49a77a8

Please sign in to comment.