blob: 4f3603495a642945585b0f17fd1d1bbaa72f0baf [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License..
//! The implementations of `Rand` for the built-in types.
use std::char;
use std::mem;
use crate::{Rand,Rng};
impl Rand for isize {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> isize {
if mem::size_of::<isize>() == 4 {
rng.gen::<i32>() as isize
} else {
rng.gen::<i64>() as isize
}
}
}
impl Rand for i8 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> i8 {
rng.next_u32() as i8
}
}
impl Rand for i16 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> i16 {
rng.next_u32() as i16
}
}
impl Rand for i32 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> i32 {
rng.next_u32() as i32
}
}
impl Rand for i64 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> i64 {
rng.next_u64() as i64
}
}
impl Rand for i128 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> i128 {
rng.gen::<u128>() as i128
}
}
impl Rand for usize {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> usize {
if mem::size_of::<usize>() == 4 {
rng.gen::<u32>() as usize
} else {
rng.gen::<u64>() as usize
}
}
}
impl Rand for u8 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> u8 {
rng.next_u32() as u8
}
}
impl Rand for u16 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> u16 {
rng.next_u32() as u16
}
}
impl Rand for u32 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> u32 {
rng.next_u32()
}
}
impl Rand for u64 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> u64 {
rng.next_u64()
}
}
impl Rand for u128 {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> u128 {
((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128)
}
}
macro_rules! float_impls {
($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
mod $mod_name {
use crate::{Rand, Rng, Open01, Closed01};
const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
impl Rand for $ty {
/// Generate a floating point number in the half-open
/// interval `[0,1)`.
///
/// See `Closed01` for the closed interval `[0,1]`,
/// and `Open01` for the open interval `(0,1)`.
#[inline]
fn rand<R: Rng>(rng: &mut R) -> $ty {
rng.$method_name()
}
}
impl Rand for Open01<$ty> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
// add a small amount (specifically 2 bits below
// the precision of f64/f32 at 1.0), so that small
// numbers are larger than 0, but large numbers
// aren't pushed to/above 1.
Open01(rng.$method_name() + 0.25 / SCALE)
}
}
impl Rand for Closed01<$ty> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
// rescale so that 1.0 - epsilon becomes 1.0
// precisely.
Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
}
}
}
}
}
float_impls! { f64_rand_impls, f64, 53, next_f64 }
float_impls! { f32_rand_impls, f32, 24, next_f32 }
impl Rand for char {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> char {
// a char is 21 bits
const CHAR_MASK: u32 = 0x001f_ffff;
loop {
// Rejection sampling. About 0.2% of numbers with at most
// 21-bits are invalid codepoints (surrogates), so this
// will succeed first go almost every time.
match char::from_u32(rng.next_u32() & CHAR_MASK) {
Some(c) => return c,
None => {}
}
}
}
}
impl Rand for bool {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> bool {
rng.gen::<u8>() & 1 == 1
}
}
macro_rules! tuple_impl {
// use variables to indicate the arity of the tuple
($($tyvar:ident),* ) => {
// the trailing commas are for the 1 tuple
impl<
$( $tyvar : Rand ),*
> Rand for ( $( $tyvar ),* , ) {
#[inline]
fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
(
// use the $tyvar's to get the appropriate number of
// repeats (they're not actually needed)
$(
_rng.gen::<$tyvar>()
),*
,
)
}
}
}
}
impl Rand for () {
#[inline]
fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
macro_rules! array_impl {
{$n:expr, $t:ident, $($ts:ident,)*} => {
array_impl!{($n - 1), $($ts,)*}
impl<T> Rand for [T; $n] where T: Rand {
#[inline]
fn rand<R: Rng>(_rng: &mut R) -> [T; $n] {
[_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
}
}
};
{$n:expr,} => {
impl<T> Rand for [T; $n] {
fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { [] }
}
};
}
array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
impl<T:Rand> Rand for Option<T> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Option<T> {
if rng.gen() {
Some(rng.gen())
} else {
None
}
}
}