Search results

There are no results.

std.rand.Random

type pub Random

A cryptographically secure pseudo random number generator (CSPRNG).

The underlying algorithm is ChaCha8, loosely based on Go's ChaCha8 CSPRNG as described here, and Pony's random number generation code as found here and here.

Fast-key-erasure is applied in an attempt to make attacks against the RNG more difficult.

While the current implementation should be sufficient/not obviously broken, it hasn't been formally verified or audited and thus may still contain some flaws.

Static methods

from_int

Show source code
Hide source code
fn pub static from_int(value: Int) -> Self {
  let seed = ByteArray.filled(with: 0, times: SEED_SIZE)

  little.write_i64(value, into: seed, at: 0)
  with_seed(seed)
}
fn pub static from_int(value: Int) -> Random

Returns a new Random using the given Int as its seed.

Random instances created using this method are not suitable for cryptography, as a single Int doesn't produce enough entropy. For cryptography you must use Random.new instead.

Refer to the documentation of Random.new for more details.

Examples

import std.rand (Random)

Random.from_int(42)

new

Show source code
Hide source code
fn pub static new -> Self {
  let seed = ByteArray.new

  sys.random_bytes(into: seed, size: SEED_SIZE)
  with_seed(seed)
}
fn pub static new -> Random

Returns a new Random seeded using a cryptographically secure seed.

The seed is generated using the operating system's CSPRNG.

While creating a Random instance isn't necessarily expensive, it's not cheap either. As such it's best to create an instance (or multiple instances) ahead of time and reuse them, instead of creating them on the fly.

Examples

import std.rand (Random)

Random.new

Instance methods

bytes

Show source code
Hide source code
fn pub mut bytes(into: mut ByteArray, size: Int) {
  let mut rem = size

  while rem > 0 {
    if @index == BUFFER_SIZE { refill }

    let idx = @index
    let end = min(idx + rem, @buffer.size)
    let len = end - idx

    into.append(@buffer.slice(start: idx, end: end))
    zero(idx, len)
    rem = rem.wrapping_sub(len)
    @index = idx.wrapping_add(len)
  }
}
fn pub mut bytes(into: mut ByteArray, size: Int)

Generates size random bytes and appends them to into.

Examples

import std.rand (Random)

let rng = Random.from_int(10)
let buf = ByteArray.new

rng.bytes(into: buf, size: 8)
buf # => ByteArray.from_array([14, 98, 139, 15, 133, 67, 84, 178])

float

Show source code
Hide source code
fn pub mut float -> Float {
  (int >>> 11).to_float * (1.0 / 9007199254740992.0)
}
fn pub mut float -> Float

Returns a randomly generated Float in the end exclusive range 0.0..1.0.

Examples

import std.rand (Random)

let rng = Random.from_int(10)

rng.float # => 0.6965982627730631

float_between

Show source code
Hide source code
fn pub mut float_between(min: Float, max: Float) -> Float {
  if min > max { invalid_range_error(min, max) }

  float * (max - min) + min
}
fn pub mut float_between(min: Float, max: Float) -> Float

Returns a randomly generated Float uniformly distributed in the given end exclusive range.

Panics

This method panics if min is greater than max.

Examples

import std.rand (Random)

let rng = Random.from_int(10)

rng.float_between(1.0, 10.0) # => 7.269384364957569

int

Show source code
Hide source code
fn pub mut int -> Int {
  if @index == BUFFER_SIZE { refill }

  let idx = @index := @index.wrapping_add(8)
  let val = little.read_i64(@buffer, at: idx)

  zero(idx, size: 8)
  val
}
fn pub mut int -> Int

Returns a randomly generated Int in the end exclusive range MIN..MAX where MIN is the minimum value of a 64-bits signed integer and MAX the maximum value.

Examples

import std.rand (Random)

let rng = Random.from_int(10)

rng.int # => -5596774198144179698

int_between

Show source code
Hide source code
fn pub mut int_between(min: Int, max: Int) -> Int {
  if min > max { invalid_range_error(min, max) }

  # Apple's approach as taken from
  # https://www.pcg-random.org/posts/bounded-rands.html, as we can't use
  # Lemire's approach as that requires 128 bits integer support.
  let mut mask = -1
  let range = max.wrapping_sub(min).wrapping_sub(1)

  mask >>>= (range | 1).leading_zeros

  loop {
    match int & mask {
      case v if v <= range -> return min.wrapping_add(v)
      case _ -> {}
    }
  }
}
fn pub mut int_between(min: Int, max: Int) -> Int

Returns a randomly generated Int uniformly distributed in the given end exclusive range.

Panics

This method panics if min is greater than max.

Examples

import std.rand (Random)

let rng = Random.from_int(10)

rng.int_between(1, 10) # => 8