Portability

Definitions

Given fixed inputs, all items (should) fall into one of three categories:

  • Output is non-deterministic, thus never reproducible
  • Output is deterministic, but not considered portable
  • Output is deterministic and portable

In general, functionality is considered deterministic and portable unless it is clearly non-deterministic (e.g. getrandom, ThreadRng) or it is documented as being unportable (e.g. StdRng, SmallRng).

Crate versions

We try to follow semver rules regarding API-breaking changes and MAJOR.MINOR.PATCH versions:

  • New patch versions should not include API-breaking changes or major new features
  • Before 1.0, minor versions may include API breaking changes. After 1.0 they should not.

Additionally, we must also consider value-breaking changes and portability. When given fixed inputs,

  • For non-deterministic items, implementations may change in any release
  • For deterministic unportable items, output should be preserved in patch releases, but may change in any minor release (including after 1.0)
  • For portable items, any change of output across versions is considered equivalent to an API breaking change.

Testing

We expect all pseudo-random algorithms to test the value-stability of their output, where possible:

  • PRNGs should be compared with a reference vector (example)
  • Other algorithms should include their own test vectors within a value_stability test or similar (example)

Limitations

Portability of usize

There is unfortunately one non-portable item baked into the heart of the Rust language: usize (and isize). For example, the size of an empty Vec will differ on 32-bit and 64-bit targets. For most purposes this is not an issue, but when it comes to generating random numbers in a portable manner it does matter.

A simple rule follows: if portability is required, never sample a usize or isize value directly.

Within Rand we adhere to this rule whenever possible. All sequence-releated code requiring a bounded usize value will sample a u32 value unless the upper bound exceeds u32::MAX. (Note that this actually improves benchmark performance in many cases.)

Portability of floats

The results of floating point arithmetic depend on rounding modes and implementation details. Especially the results of transcendental functions vary from platform to platform. Due to this, the distributions in rand_distr are not always portable for f32 and f64. However, we strive to make them as portable as possible.