randomkit/
lib.rs

1//! Nonuniform pseudorandom number generation
2//!
3//! This library provides a suite of nonuniform random number generators
4//! via bindings to the Numpy fork of RandomKit. It is approximately
5//! equivalent to Numpy's `numpy.random` module. The API is loosely
6//! based on that of the [`rand`](https://github.com/rust-lang/rand)
7//! crate.
8//!
9//! This library is not suitable for cryptography.
10//!
11//! # Usage
12//!
13//! Add this to your `Cargo.toml`:
14//!
15//! ```toml
16//! [dependencies]
17//! randomkit = "0.1"
18//! ```
19//!
20//! and this to your crate root:
21//!
22//! ```rust
23//! extern crate randomkit;
24//! ```
25//!
26//! # Examples
27//!
28//! ## Standard normal distribution
29//!
30//! Sample 1000 numbers from the standard normal distribution (Gauss
31//! distribution) with mean 0 and standard deviation 1.
32//!
33//! ```rust
34//! extern crate randomkit;
35//!
36//! use randomkit::{Rng, Sample};
37//! use randomkit::dist::Gauss;
38//!
39//! fn main() {
40//!     let mut rng = Rng::new().unwrap();
41//!     for _ in 0..1000 {
42//!         println!("{}", Gauss.sample(&mut rng));
43//!     }
44//! }
45//! ```
46//!
47//! ## Normal distribution
48//!
49//! Sample 1000 numbers from a normal distribution with mean 10 and
50//! standard deviation 5.
51//!
52//! ```rust
53//! extern crate randomkit;
54//!
55//! use randomkit::{Rng, Sample};
56//! use randomkit::dist::Normal;
57//!
58//! fn main() {
59//!     let mut rng = Rng::from_seed(1);
60//!     let normal = Normal::new(10.0, 5.0).unwrap();
61//!     for _ in 0..1000 {
62//!         println!("{}", normal.sample(&mut rng));
63//!     }
64//! }
65//! ```
66
67#![crate_name = "randomkit"]
68
69extern crate libc;
70
71use std::mem;
72use libc::c_ulong;
73
74pub mod dist;
75mod ffi;
76
77pub struct Rng { state: ffi::RkState }
78
79impl Rng {
80    unsafe fn uninitialized() -> Rng {
81        Rng { state: mem::uninitialized() }
82    }
83
84    /// Initialize a new pseudorandom number generator from a seed.
85    pub fn from_seed(seed: u32) -> Rng {
86        // Seed is &'d with 0xffffffff in randomkit.c, so there's no
87        // point in making it larger.
88        unsafe {
89            let mut r = Rng::uninitialized();
90            ffi::rk_seed(seed as c_ulong, &mut r.state);
91            r
92        }
93    }
94
95    /// Initialize a new pseudorandom number generator using the
96    /// operating system's random number generator as the seed.
97    pub fn new() -> Option<Rng> {
98        unsafe {
99            let mut r = Rng::uninitialized();
100            match ffi::rk_randomseed(&mut r.state) {
101                ffi::RkError::RkNoerr => Some(r),
102                _ => None,
103            }
104        }
105    }
106}
107
108pub trait Sample<Support> {
109    /// Generate a pseudorandom element of `Support` using `rng` as the
110    /// source of randomness.
111    fn sample(&self, rng: &mut Rng) -> Support;
112}