rug 0.9.3

Arbitrary-precision integers, rational, floating-point and complex numbers based on GMP, MPFR and MPC
Documentation
// Copyright © 2016–2018 University of Malta

// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.

//! Random number generation.

// UNDEFINED BEHAVIOUR WARNING:
//
// Not all the fields of randstate_t are used, and thus GMP does not
// initialize all the fields. So we must use mem::zeroed rather than
// mem::uninitialized, otherwise we may have uninitialized memory
// which can eventually lead to undefined behaviour.

use Integer;
use inner::{Inner, InnerMut};

use cast::cast;
use gmp_mpfr_sys::gmp::{self, randstate_t};
use std::marker::PhantomData;
use std::mem;
use std::os::raw::{c_int, c_ulong, c_void};
use std::panic::{self, AssertUnwindSafe};
use std::process;
use std::ptr;

/// The state of a random number generator.
///
/// # Examples
///
/// ```rust
/// use rug::rand::RandState;
/// let mut rand = RandState::new();
/// let u = rand.bits(32);
/// println!("32 random bits: {:032b}", u);
/// ```
pub struct RandState<'a> {
    inner: randstate_t,
    phantom: PhantomData<&'a RandGen>,
}

impl<'a> Default for RandState<'a> {
    #[inline]
    fn default() -> RandState<'a> {
        RandState::new()
    }
}

impl<'a> Clone for RandState<'a> {
    #[inline]
    fn clone(&self) -> RandState<'a> {
        unsafe {
            let mut inner = mem::zeroed();
            gmp::randinit_set(&mut inner, self.inner());
            // If d is null, then boxed_clone must have returned None.
            let ptr = &inner as *const _ as *const MpRandState;
            if (*ptr).seed.d.is_null() {
                panic!("`RandGen::boxed_clone` returned `None`");
            }
            RandState {
                inner,
                phantom: PhantomData,
            }
        }
    }
}

impl<'a> Drop for RandState<'a> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            gmp::randclear(self.inner_mut());
        }
    }
}

unsafe impl<'a> Send for RandState<'a> {}
unsafe impl<'a> Sync for RandState<'a> {}

impl<'a> RandState<'a> {
    /// Creates a new random generator with a compromise between speed
    /// and randomness.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandState;
    /// let mut rand = RandState::new();
    /// let u = rand.bits(32);
    /// println!("32 random bits: {:032b}", u);
    /// ```
    #[inline]
    pub fn new() -> RandState<'a> {
        unsafe {
            let mut inner = mem::zeroed();
            gmp::randinit_default(&mut inner);
            RandState {
                inner,
                phantom: PhantomData,
            }
        }
    }

    /// Creates a random generator with a Mersenne Twister algorithm.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandState;
    /// let mut rand = RandState::new_mersenne_twister();
    /// let u = rand.bits(32);
    /// println!("32 random bits: {:032b}", u);
    /// ```
    pub fn new_mersenne_twister() -> RandState<'a> {
        unsafe {
            let mut inner = mem::zeroed();
            gmp::randinit_mt(&mut inner);
            RandState {
                inner,
                phantom: PhantomData,
            }
        }
    }

    /// Creates a new random generator with a linear congruential
    /// algorithm *X* = (*a* × *X* + *c*) mod 2<sup>*bits*</sup>.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::Integer;
    /// use rug::rand::RandState;
    /// let a = match Integer::from_str_radix("292787ebd3329ad7e7575e2fd", 16) {
    ///     Ok(i) => i,
    ///     Err(_) => unreachable!(),
    /// };
    /// let c = 1;
    /// let bits = 100;
    /// let mut rand = RandState::new_linear_congruential(&a, c, bits);
    /// let u = rand.bits(32);
    /// println!("32 random bits: {:032b}", u);
    /// ```
    pub fn new_linear_congruential(
        a: &Integer,
        c: u32,
        bits: u32,
    ) -> RandState<'a> {
        unsafe {
            let mut inner = mem::zeroed();
            gmp::randinit_lc_2exp(&mut inner, a.inner(), c.into(), bits.into());
            RandState {
                inner,
                phantom: PhantomData,
            }
        }
    }

    /// Creates a new random generator with a linear congruential
    /// algorithm like the [`new_linear_congruential`][cong] method.
    ///
    /// For the linear congrentail algorithm *X* = (*a* × *X* + *c*)
    /// mod 2<sup>*bits*</sup>, *a*, *c* and *bits* are selected from
    /// a table such that at least *size* bits of each *X* will be
    /// used, that is *bits* ≥ *size*. The table only has values for a
    /// size of up to 256 bits; `None` will be returned if the
    /// requested size is larger.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandState;
    /// let mut rand = match RandState::new_linear_congruential_size(100) {
    ///     Some(r) => r,
    ///     None => unreachable!(),
    /// };
    /// let u = rand.bits(32);
    /// println!("32 random bits: {:032b}", u);
    /// ```
    ///
    /// [cong]: #method.new_linear_congruential
    pub fn new_linear_congruential_size(size: u32) -> Option<RandState<'a>> {
        unsafe {
            let mut inner = mem::zeroed();
            if gmp::randinit_lc_2exp_size(&mut inner, size.into()) != 0 {
                Some(RandState {
                    inner,
                    phantom: PhantomData,
                })
            } else {
                None
            }
        }
    }

    /// Creates a new custom random generator.
    ///
    /// If the custom random generator is cloned, the implemented
    /// trait method
    /// [`RandGen::boxed_clone`](trait.RandGen.html#method.boxed_clone)
    /// is called; this leads to panic if the method returns `None`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::Integer;
    /// use rug::rand::{RandGen, RandState};
    /// struct Seed;
    /// impl RandGen for Seed {
    ///     fn gen(&mut self) -> u32 { 0x8cef7310 }
    /// }
    /// let mut seed = Seed;
    /// let mut rand = RandState::new_custom(&mut seed);
    /// let mut i = Integer::from(15);
    /// i.random_below_mut(&mut rand);
    /// println!("0 ≤ {} < 15", i);
    /// assert!(i < 15);
    /// ```
    pub fn new_custom(custom: &'a mut RandGen) -> RandState<'a> {
        let b: Box<&'a mut RandGen> = Box::new(custom);
        let r_ptr: *mut &mut RandGen = Box::into_raw(b);
        let inner = MpRandState {
            seed: gmp::mpz_t {
                alloc: 0,
                size: 0,
                d: r_ptr as *mut gmp::limb_t,
            },
            alg: 0,
            algdata: &CUSTOM_FUNCS as *const _ as *mut _,
        };
        RandState {
            inner: unsafe { mem::transmute(inner) },
            phantom: PhantomData,
        }
    }

    /// Creates a new custom random generator.
    ///
    /// If the custom random generator is cloned, the implemented
    /// trait method
    /// [`RandGen::boxed_clone`](trait.RandGen.html#method.boxed_clone)
    /// is called; this leads to panic if the method returns `None`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::Integer;
    /// use rug::rand::{RandGen, RandState};
    /// struct Seed;
    /// impl RandGen for Seed {
    ///     fn gen(&mut self) -> u32 { 0x8cef7310 }
    /// }
    /// let seed = Box::new(Seed);
    /// let mut rand = RandState::new_custom_boxed(seed);
    /// let mut i = Integer::from(15);
    /// i.random_below_mut(&mut rand);
    /// println!("0 ≤ {} < 15", i);
    /// assert!(i < 15);
    /// ```
    pub fn new_custom_boxed(custom: Box<RandGen>) -> RandState<'a> {
        let b: Box<Box<RandGen>> = Box::new(custom);
        let r_ptr: *mut Box<RandGen> = Box::into_raw(b);
        let inner = MpRandState {
            seed: gmp::mpz_t {
                alloc: 0,
                size: 0,
                d: r_ptr as *mut gmp::limb_t,
            },
            alg: 0,
            algdata: &CUSTOM_BOXED_FUNCS as *const _ as *mut _,
        };
        RandState {
            inner: unsafe { mem::transmute(inner) },
            phantom: PhantomData,
        }
    }

    /// Seeds the random generator.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::Integer;
    /// use rug::rand::RandState;
    /// let seed = Integer::from(123456);
    /// let mut rand = RandState::new();
    /// rand.seed(&seed);
    /// let u1a = rand.bits(32);
    /// let u1b = rand.bits(32);
    /// // reseed with the same seed
    /// rand.seed(&seed);
    /// let u2a = rand.bits(32);
    /// let u2b = rand.bits(32);
    /// assert_eq!(u1a, u2a);
    /// assert_eq!(u1b, u2b);
    /// ```
    #[inline]
    pub fn seed(&mut self, seed: &Integer) {
        unsafe {
            gmp::randseed(self.inner_mut(), seed.inner());
        }
    }

    /// Generates a random number with the specified number of bits.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandState;
    /// let mut rand = RandState::new();
    /// let u = rand.bits(16);
    /// assert!(u < (1 << 16));
    /// println!("16 random bits: {:016b}", u);
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if `bits` is greater than 32.
    #[inline]
    pub fn bits(&mut self, bits: u32) -> u32 {
        assert!(bits <= 32, "bits out of range");
        unsafe { gmp::urandomb_ui(self.inner_mut(), bits.into()) as u32 }
    }

    /// Generates a random number below the given boundary value.
    ///
    /// This function can never return the maximum 32-bit value; in
    /// order to generate a 32-bit random value that covers the whole
    /// range, use the [`bits`](#method.bits) method with `bits` set
    /// to 32.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandState;
    /// let mut rand = RandState::new();
    /// let u = rand.below(10000);
    /// assert!(u < 10000);
    /// println!("0 ≤ {} < 10000", u);
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if the boundary value is zero.
    #[inline]
    pub fn below(&mut self, bound: u32) -> u32 {
        assert_ne!(bound, 0, "cannot be below zero");
        unsafe { gmp::urandomm_ui(self.inner_mut(), bound.into()) as u32 }
    }

    /// Creates a random generator from an initialized GMP random
    /// generator.
    ///
    /// # Safety
    ///
    /// * The value must be initialized. Note that the GMP functions
    ///   do not initialize all fields of the
    ///   `gmp_mpfr_sys::gmp::randstate_t` object, which can
    ///   eventually lead to reading uninitialized memory, and that is
    ///   undefined behaviour in Rust even if no decision is made
    ///   using the read value. One way to ensure that there is no
    ///   uninitialized memory inside `raw` is to use `mem::zeroed` to
    ///   initialize `raw` before initializing with a function such as
    ///   `gmp_mpfr_sys::gmp::randinit_default`, like in the example
    ///   below.
    /// * The `gmp_mpfr_sys::gmp::randstate_t` type can be considered
    ///   as a kind of pointer, so there can be multiple copies of it.
    ///   Since this function takes over ownership, no other copies of
    ///   the passed value should exist.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate gmp_mpfr_sys;
    /// extern crate rug;
    /// use gmp_mpfr_sys::gmp;
    /// use rug::rand::RandState;
    /// use std::mem;
    /// fn main() {
    ///     let mut rand = unsafe {
    ///         // Do not use mem::uninitialized, as gmp::randinit_default
    ///         // does not initialize all of the fields of raw.
    ///         let mut raw = mem::zeroed();
    ///         gmp::randinit_default(&mut raw);
    ///         // raw is initialized and unique
    ///         RandState::from_raw(raw)
    ///     };
    ///     let u = rand.bits(32);
    ///     println!("32 random bits: {:032b}", u);
    ///     // since rand is a RandState now, deallocation is automatic
    /// }
    /// ```
    #[inline]
    pub unsafe fn from_raw(raw: randstate_t) -> RandState<'a> {
        RandState {
            inner: raw,
            phantom: PhantomData,
        }
    }

    /// Converts a random generator into a GMP random generator.
    ///
    /// The returned object should be freed to avoid memory leaks.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate gmp_mpfr_sys;
    /// extern crate rug;
    /// use gmp_mpfr_sys::gmp;
    /// use rug::rand::RandState;
    /// fn main() {
    ///     let rand = RandState::new();
    ///     let mut raw = rand.into_raw();
    ///     unsafe {
    ///         let u = gmp::urandomb_ui(&mut raw, 32) as u32;
    ///         println!("32 random bits: {:032b}", u);
    ///         // free object to prevent memory leak
    ///         gmp::randclear(&mut raw);
    ///     }
    /// }
    /// ```
    #[inline]
    pub fn into_raw(self) -> randstate_t {
        let ret = self.inner;
        mem::forget(self);
        ret
    }

    /// Returns a pointer to the internal GMP random generator.
    ///
    /// The returned pointer will be valid for as long as `self` is
    /// valid.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandState;
    /// let mut rand = RandState::new();
    /// let raw_ptr = rand.as_raw();
    /// // There is not much you can do with an immutable randstate_t pointer.
    /// println!("pointer: {:p}", raw_ptr);
    /// let u = rand.bits(32);
    /// println!("32 random bits: {:032b}", u);
    /// ```
    #[inline]
    pub fn as_raw(&mut self) -> *const randstate_t {
        self.inner()
    }

    /// Returns an unsafe mutable pointer to the internal GMP random
    /// generator.
    ///
    /// The returned pointer will be valid for as long as `self` is
    /// valid.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate gmp_mpfr_sys;
    /// extern crate rug;
    /// use gmp_mpfr_sys::gmp;
    /// use rug::rand::RandState;
    /// fn main() {
    ///     let mut rand = RandState::new();
    ///     let raw_ptr = rand.as_raw_mut();
    ///     unsafe {
    ///         let u1 = gmp::urandomb_ui(raw_ptr, 32) as u32;
    ///         println!("32 random bits: {:032b}", u1);
    ///     }
    ///     let u2 = rand.bits(32);
    ///     println!("another 32 random bits: {:032b}", u2);
    /// }
    /// ```
    #[inline]
    pub fn as_raw_mut(&mut self) -> *mut randstate_t {
        unsafe { self.inner_mut() }
    }
}

/// Custom random number generator to be used with
/// [`RandState`](struct.RandState.html).
///
/// # Examples
///
/// ```rust
/// use rug::Integer;
/// use rug::rand::RandGen;
/// struct SimpleGenerator {
///     seed: u64,
/// }
/// impl RandGen for SimpleGenerator {
///     fn gen(&mut self) -> u32 {
///         self.seed =
///             self.seed.wrapping_mul(6364136223846793005).wrapping_add(1);
///         (self.seed >> 32) as u32
///     }
///     fn seed(&mut self, seed: &Integer) {
///         self.seed = seed.to_u64_wrapping();
///     }
/// }
/// let mut rand = SimpleGenerator { seed: 1 };
/// assert_eq!(rand.gen(), 1481765933);
/// assert_eq!(rand.seed, 6364136223846793006);
/// ```
pub trait RandGen: Send + Sync {
    /// Gets a random 32-bit unsigned integer.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandGen;
    /// struct SimpleGenerator {
    ///     seed: u64,
    /// }
    /// impl RandGen for SimpleGenerator {
    ///     fn gen(&mut self) -> u32 {
    ///         self.seed =
    ///             self.seed.wrapping_mul(6364136223846793005).wrapping_add(1);
    ///         (self.seed >> 32) as u32
    ///     }
    /// }
    /// let mut rand = SimpleGenerator { seed: 1 };
    /// let first = rand.gen();
    /// assert_eq!(rand.seed, 6364136223846793006);
    /// assert_eq!(first, 1481765933);
    /// let second = rand.gen();
    /// assert_eq!(rand.seed, 13885033948157127959);
    /// assert_eq!(second, 3232861391);
    /// ```
    fn gen(&mut self) -> u32;

    /// Gets up to 32 random bits.
    ///
    /// The default implementation simply calls the
    /// [`gen`](#tymethod.gen) method once and returns the most
    /// significant required bits.
    ///
    /// This method can be overridden to store any unused bits for
    /// later use. This can be useful for example if the random number
    /// generation process is computationally expensive.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandGen;
    /// struct SimpleGenerator {
    ///     seed: u64,
    ///     buffer: u64,
    ///     len: u32,
    /// }
    /// impl RandGen for SimpleGenerator {
    ///     fn gen(&mut self) -> u32 {
    ///         self.gen_bits(32)
    ///     }
    ///     fn gen_bits(&mut self, bits: u32) -> u32 {
    ///         let mut bits = match bits {
    ///             0 => return 0,
    ///             1...31 => bits,
    ///             _ => 32,
    ///         };
    ///         let mut ret = 0;
    ///         if bits > self.len {
    ///             bits -= self.len;
    ///             ret |= (self.buffer << bits) as u32;
    ///             self.seed = self.seed.wrapping_mul(6364136223846793005);
    ///             self.seed = self.seed.wrapping_add(1);
    ///             self.buffer = self.seed;
    ///             self.len = 64;
    ///         }
    ///         self.len -= bits;
    ///         ret |= (self.buffer >> self.len) as u32;
    ///         self.buffer &= !(!0 << self.len);
    ///         ret
    ///     }
    /// }
    /// let mut rand = SimpleGenerator { seed: 1, buffer: 0, len: 0 };
    /// let full = 6364136223846793006_u64;
    /// assert_eq!(rand.gen_bits(16), (full >> 48) as u32);
    /// assert_eq!(rand.gen_bits(32), (full >> 16) as u32);
    /// assert_eq!(rand.gen_bits(16), full as u32 & 0xffff);
    /// ```
    fn gen_bits(&mut self, bits: u32) -> u32 {
        let gen = self.gen();
        match bits {
            0 => 0,
            1...32 => gen >> (32 - bits),
            _ => gen,
        }
    }

    /// Seeds the random number generator.
    ///
    /// The default implementation of this function does nothing.
    ///
    /// Note that the [`RandState::seed`][seed] method will pass its
    /// seed parameter exactly to this function without using it
    /// otherwise.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::{Assign, Integer};
    /// use rug::rand::{RandGen, RandState};
    /// struct Seed { inner: Integer };
    /// impl RandGen for Seed {
    ///     fn gen(&mut self) -> u32 { self.inner.to_u32_wrapping() }
    ///     fn seed(&mut self, seed: &Integer) {
    ///         self.inner.assign(seed);
    ///     }
    /// }
    /// let mut seed = Seed { inner: Integer::from(12) };
    /// let i = Integer::from(12345);
    /// {
    ///     let mut rand = RandState::new_custom(&mut seed);
    ///     rand.seed(&i);
    /// }
    /// assert_eq!(seed.inner, i);
    /// ```
    ///
    /// Since the seed parameter is only passed to this function and
    /// not used otherwise, with unsafe code you can pass a reference
    /// to anything, or even an `isize` or `usize`, to the seeding
    /// function.
    ///
    /// ```rust
    /// use rug::Integer;
    /// use rug::rand::{RandGen, RandState};
    /// use std::mem;
    /// struct Seed { num: isize };
    /// impl RandGen for Seed {
    ///     fn gen(&mut self) -> u32 { 0x8cef7310 }
    ///     fn seed(&mut self, seed: &Integer) {
    ///         // unsafe code to transmute from &Integer to isize
    ///         self.num = unsafe { mem::transmute(seed) };
    ///     }
    /// }
    /// let mut seed = Seed { num: 15 };
    /// let i = -12345_isize;
    /// {
    ///     // unsafe code to transmute from isize to &Integer
    ///     let ir = unsafe { mem::transmute(i) };
    ///     let mut rand = RandState::new_custom(&mut seed);
    ///     rand.seed(ir);
    /// }
    /// assert_eq!(seed.num, i);
    /// ```
    ///
    /// [seed]: struct.RandState.html#method.seed
    #[inline]
    fn seed(&mut self, seed: &Integer) {
        let _ = seed;
    }

    /// Optionally clones the random number generator.
    ///
    /// The default implementation returns `None`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rug::rand::RandGen;
    /// struct SimpleGenerator {
    ///     seed: u64,
    /// }
    /// impl RandGen for SimpleGenerator {
    ///     fn gen(&mut self) -> u32 {
    ///         self.seed =
    ///             self.seed.wrapping_mul(6364136223846793005).wrapping_add(1);
    ///         (self.seed >> 32) as u32
    ///     }
    ///     fn boxed_clone(&self) -> Option<Box<RandGen>> {
    ///         let other = SimpleGenerator { seed: self.seed };
    ///         let boxed = Box::new(other);
    ///         Some(boxed)
    ///     }
    /// }
    /// let mut rand = SimpleGenerator { seed: 1 };
    /// let first = rand.gen();
    /// assert_eq!(rand.seed, 6364136223846793006);
    /// assert_eq!(first, 1481765933);
    /// let mut other = rand.boxed_clone().unwrap();
    /// let second = rand.gen();
    /// assert_eq!(rand.seed, 13885033948157127959);
    /// assert_eq!(second, 3232861391);
    /// let second_other = other.gen();
    /// assert_eq!(second_other, 3232861391);
    /// ```
    #[inline]
    fn boxed_clone(&self) -> Option<Box<RandGen>> {
        None
    }
}

// The contents of gmp::randstate_t are not available because the
// internal details of gmp_randstate_t are not documented by GMP. So
// we duplcate them here. The structure of function pointers
// gmp_randfnptr_t is only inside gmp-impl.h and is not available
// externally, so we duplicate it here as well.

#[repr(C)]
struct MpRandState {
    seed: gmp::mpz_t,
    alg: c_int,
    algdata: *mut c_void,
}

#[repr(C)]
struct Funcs {
    seed: Option<unsafe extern "C" fn(*mut randstate_t, *const gmp::mpz_t)>,
    get: Option<
        unsafe extern "C" fn(*mut randstate_t, *mut gmp::limb_t, c_ulong),
    >,
    clear: Option<unsafe extern "C" fn(*mut randstate_t)>,
    iset: Option<unsafe extern "C" fn(*mut randstate_t, *const randstate_t)>,
}

macro_rules! c_callback {
    { $(fn $func:ident($($param:tt)*) $body:block)* } => {
        $(
            unsafe extern "C" fn $func($($param)*) {
                panic::catch_unwind(AssertUnwindSafe(|| $body))
                    .unwrap_or_else(|_| process::abort())
            }
        )*
    }
}

c_callback! {
    fn abort_seed(_: *mut randstate_t, _: *const gmp::mpz_t) {
        process::abort();
    }

    fn abort_get(_: *mut randstate_t, _: *mut gmp::limb_t, _: c_ulong) {
        process::abort();
    }

    fn abort_clear(_: *mut randstate_t) {
        process::abort();
    }

    fn abort_iset(_: *mut randstate_t, _: *const randstate_t) {
        process::abort();
    }

    fn custom_seed(s: *mut randstate_t, seed: *const gmp::mpz_t) {
        let s_ptr = s as *mut MpRandState;
        let r_ptr = (*s_ptr).seed.d as *mut &mut RandGen;
        (*r_ptr).seed(&(*(seed as *const Integer)));
    }

    fn custom_get(s: *mut randstate_t, limb: *mut gmp::limb_t, bits: c_ulong) {
        let s_ptr = s as *mut MpRandState;
        let r_ptr = (*s_ptr).seed.d as *mut &mut RandGen;
        gen_bits(*r_ptr, limb, bits);
    }

    fn custom_clear(s: *mut randstate_t) {
        let s_ptr = s as *mut MpRandState;
        let r_ptr = (*s_ptr).seed.d as *mut &mut RandGen;
        drop(Box::from_raw(r_ptr));
    }

    fn custom_iset(dst: *mut randstate_t, src: *const randstate_t) {
        let src_ptr = src as *const MpRandState;
        let r_ptr = (*src_ptr).seed.d as *const &mut RandGen;
        gen_copy(*r_ptr, dst);
    }

    fn custom_boxed_seed(s: *mut randstate_t, seed: *const gmp::mpz_t) {
        let s_ptr = s as *mut MpRandState;
        let r_ptr = (*s_ptr).seed.d as *mut Box<RandGen>;
        (*r_ptr).seed(&(*(seed as *const Integer)));
    }

    fn custom_boxed_get(
        s: *mut randstate_t,
        limb: *mut gmp::limb_t,
        bits: c_ulong,
    ) {
        let s_ptr = s as *mut MpRandState;
        let r_ptr = (*s_ptr).seed.d as *mut Box<RandGen>;
        gen_bits(&mut **r_ptr, limb, bits);
    }

    fn custom_boxed_clear(s: *mut randstate_t) {
        let s_ptr = s as *mut MpRandState;
        let r_ptr = (*s_ptr).seed.d as *mut Box<RandGen>;
        drop(Box::from_raw(r_ptr));
    }

    fn custom_boxed_iset(dst: *mut randstate_t, src: *const randstate_t) {
        let src_ptr = src as *const MpRandState;
        let r_ptr = (*src_ptr).seed.d as *const Box<RandGen>;
        gen_copy(&**r_ptr, dst);
    }
}

#[cfg(gmp_limb_bits_64)]
unsafe fn gen_bits(gen: &mut RandGen, limb: *mut gmp::limb_t, bits: c_ulong) {
    let (limbs, rest) = (bits / 64, bits % 64);
    let limbs: isize = cast(limbs);
    for i in 0..limbs {
        let n = u64::from(gen.gen()) | u64::from(gen.gen()) << 32;
        *limb.offset(i) = cast(n);
    }
    if rest >= 32 {
        let mut n = u64::from(gen.gen());
        if rest > 32 {
            let mask = !(!0 << (rest - 32));
            n |= u64::from(gen.gen_bits(cast(rest - 32)) & mask) << 32;
        }
        *limb.offset(limbs) = cast(n);
    } else if rest > 0 {
        let mask = !(!0 << rest);
        let n = u64::from(gen.gen_bits(cast(rest)) & mask);
        *limb.offset(limbs) = cast(n);
    }
}

#[cfg(gmp_limb_bits_32)]
unsafe fn gen_bits(gen: &mut RandGen, limb: *mut gmp::limb_t, bits: c_ulong) {
    let (limbs, rest) = (bits / 32, bits % 32);
    let limbs: isize = cast(limbs);
    for i in 0..limbs {
        *limb.offset(i) = cast(gen.gen());
    }
    if rest > 0 {
        let mask = !(!0 << rest);
        *limb.offset(limbs) = cast(gen.gen_bits(cast(rest)) & mask);
    }
}

unsafe fn gen_copy(gen: &RandGen, dst: *mut randstate_t) {
    let other = gen.boxed_clone();
    // Do not panic here if other is None, as panics cannot cross FFI
    // boundareies. Instead, set dst_ptr.seed.d to null.
    let (dst_r_ptr, funcs) = if let Some(other) = other {
        let b: Box<Box<RandGen>> = Box::new(other);
        let dst_r_ptr: *mut Box<RandGen> = Box::into_raw(b);
        let funcs = &CUSTOM_BOXED_FUNCS as *const _ as *mut _;
        (dst_r_ptr, funcs)
    } else {
        (ptr::null_mut(), &ABORT_FUNCS as *const _ as *mut _)
    };
    let dst_ptr = dst as *mut MpRandState;
    *dst_ptr = MpRandState {
        seed: gmp::mpz_t {
            alloc: 0,
            size: 0,
            d: dst_r_ptr as *mut gmp::limb_t,
        },
        alg: 0,
        algdata: funcs,
    };
}

const ABORT_FUNCS: Funcs = Funcs {
    seed: Some(abort_seed),
    get: Some(abort_get),
    clear: Some(abort_clear),
    iset: Some(abort_iset),
};

const CUSTOM_FUNCS: Funcs = Funcs {
    seed: Some(custom_seed),
    get: Some(custom_get),
    clear: Some(custom_clear),
    iset: Some(custom_iset),
};

const CUSTOM_BOXED_FUNCS: Funcs = Funcs {
    seed: Some(custom_boxed_seed),
    get: Some(custom_boxed_get),
    clear: Some(custom_boxed_clear),
    iset: Some(custom_boxed_iset),
};

impl<'a> Inner for RandState<'a> {
    type Output = randstate_t;
    #[inline]
    fn inner(&self) -> &randstate_t {
        &self.inner
    }
}

impl<'a> InnerMut for RandState<'a> {
    #[inline]
    unsafe fn inner_mut(&mut self) -> &mut randstate_t {
        &mut self.inner
    }
}

#[cfg(test)]
mod tests {
    use rand::{RandGen, RandState};

    struct SimpleGenerator {
        seed: u64,
    }

    impl RandGen for SimpleGenerator {
        fn gen(&mut self) -> u32 {
            self.seed =
                self.seed.wrapping_mul(6364136223846793005).wrapping_add(1);
            (self.seed >> 32) as u32
        }
        fn boxed_clone(&self) -> Option<Box<RandGen>> {
            let other = SimpleGenerator { seed: self.seed };
            let boxed = Box::new(other);
            Some(boxed)
        }
    }

    #[test]
    fn check_custom_clone() {
        let mut gen = SimpleGenerator { seed: 1 };
        let third2;
        {
            let mut rand1 = RandState::new_custom(&mut gen);
            let mut rand2 = rand1.clone();
            let first1 = rand1.bits(32);
            let first2 = rand2.bits(32);
            assert_eq!(first1, first2);
            let second1 = rand1.bits(32);
            let second2 = rand2.bits(32);
            assert_eq!(second1, second2);
            assert_ne!(first1, second1);
            third2 = rand2.bits(32);
            assert_ne!(second2, third2);
        }
        let mut rand3 = RandState::new_custom_boxed(Box::new(gen));
        let mut rand4 = rand3.clone();
        let third3 = rand3.bits(32);
        let third4 = rand4.bits(32);
        assert_eq!(third2, third3);
        assert_eq!(third2, third4);
    }

    struct NoCloneGenerator;

    impl RandGen for NoCloneGenerator {
        fn gen(&mut self) -> u32 {
            0
        }
    }

    #[test]
    #[should_panic(expected = "`RandGen::boxed_clone` returned `None`")]
    fn check_custom_no_clone() {
        let mut gen = NoCloneGenerator;
        let rand1 = RandState::new_custom(&mut gen);
        rand1.clone();
    }
}