<commit_before>/*
 * PCG Random Number Generation for Rust
 *
 * Copyright 2015 <NAME> <<EMAIL>>
 *
 * Licensed 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.
 *
 * This work is derived from the implementation PCG RNG for C++ by
 * <NAME>.
 *
 * For additional information about the PCG random number generation scheme,
 * including its license and other licensing options, visit
 *
 *     http://www.pcg-random.org
 */

//! An implementation of the PCG random family of random number generators.
//! Details about the PCG generators can be found at [pcg-random.org](http://pcg-random.org)
//!
//! Currently this library provides several PCG generators:
//!
//! * `Pcg32` : 64bit LCG with an xorshift and right rotation applied to the output. To improve
//!   security only 32bits of the state are reported as output.
//! * `Pcg32Onseq` : Same as `Pcg32` but with a fixed sequence. Useful if you don't care about having
//!   multiple streams of random numbers from the same seed.
//! * `Pcg32Unique` : Same as `Pcg32` but the sequence is set by the memory location of the RNG
//!   This means that multiple `Pcg32_unique` with the same seed will produce different sequences
//!   of numbers. *NOTE*: This means that you may not get consistant results across runs of your
//!   program. If the memory location of your PCG moves for any reason such as the state of the
//!   allocator being different you will get a different stream of numbers.
//!
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/pcg_rand) and can be used by
//! adding the `pcg_rand` crate to your projects Cargo.toml
//!
//! ```toml
//! [dependencies]
//! pcg_rand = "0.12.0"
//! ```
//! # Typename Nomenclature
//! This library attempts to simplify using the PCG generators by defining easy
//! types for use. The following attempts to help you decode these typenames
//!
//! Consider the example `OneseqXshRr6432`. This consists of 4 major parts.
//!
//! 1. First is the sequence type
//! 1. Second is the permutation function
//! 1. Third is the state size in bits
//! 1. Fourth is the output size in bits
//!
//! ## Sequence types
//!
//! This library provides the following sequence types
//!
//! * `Setseq`: This is a settable stream. The random number stream can be set manually.
//! * `Unique`: This is a unique stream. Each instance of this type will be given a unique stream
//!   that cannot be modified.
//! * `Oneseq`: This is one fixed random sequence. It is hardcoded into the library and should be
//!   good enough to give good "randomness".
//! * `Mcg`: This has no random sequence it degenerates the internal LCG into a MCG. This is for
//!   speed.
//!
//! ## Permutation functions
//!
//! There are many possible permuation functions that this library can implement. Many of them are
//! composed of several indiviual components. The components that are used are:
//!
//! * `Xsh`: Refers to a High Xorshift function.
//! * `Rr`: Refers to a random rotation. Randomly rotates based on entropy from the state.
//! * `Rs`: Refers to a random shift. Randomly shifts based on entropy from the state.
//! * 'DXsM`: Refers to the Double-Xorshift and Multiply output
//!
//! # How to Use
//! The simple generators work like the other Rng's from the `rand` crate.
//! You can create a PCG as follows
//!
//! ```
//! extern crate pcg_rand;
//! extern crate rand;
//!
//! use rand::{Rng, SeedableRng};
//! use pcg_rand::Pcg32;
//!
//! fn main() {
//!     let mut pcg = Pcg32::from_entropy();
//!
//!     let x : u32 = pcg.gen();
//! }
//! ```
//!
//! The extended generators can be built in two ways, either by creating one
//! directly, or by building them from a generator at its current state.
//!
//! ```
//! extern crate pcg_rand;
//! extern crate rand;
//!
//! use pcg_rand::{
//!     Pcg32Unique,
//!     extension::{Pcg32Ext, ExtPcg, Ext256}
//! };
//! use rand::SeedableRng;
//!
//! //Create an extended generator explicitly
//! let ext1 = Pcg32Ext::<Ext256>::from_entropy();
//!
//! //Create from another PCG
//! let ext2 : ExtPcg<_,_,_,_,_,Ext256> = ExtPcg::from_pcg(Pcg32Unique::from_entropy());
//! ```
extern crate byteorder;
extern crate num_traits;
extern crate rand;
extern crate rand_core;

#[cfg(feature = "serde1")]
extern crate serde;

use rand_core::{RngCore, SeedableRng};

use std::num::Wrapping;

pub mod extension;
pub mod multiplier;
pub mod numops;
pub mod outputmix;
pub mod seeds;
pub mod stream;

#[cfg(feature = "serde1")]
pub mod serialization;

#[cfg(feature = "serde1")]
use serde::{Deserialize, Serialize};

use multiplier::{DefaultMultiplier, McgMultiplier, Multiplier};
use num_traits::{One, Zero};
use numops::*;
use outputmix::{DXsMMixin, OutputMixin, XshRrMixin, XshRsMixin};
use seeds::PcgSeeder;
use stream::{NoSeqStream, OneSeqStream, SpecificSeqStream, Stream, UniqueSeqStream};

use std::marker::PhantomData;

/// A generic PCG structure.
///
/// This structure allows the building of many types of PCG generators by using various
/// Mixins for both the stream, multiplier, and permutation function.
pub struct PcgEngine<
    Itype,
    Xtype,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
> {
    state: Itype,
    stream_mix: StreamMix,
    mul_mix: PhantomData<MulMix>,
    out_mix: PhantomData<OutMix>,
    phantom: PhantomData<Xtype>,
}

impl<Itype, Xtype, StreamMix, MulMix, OutMix> PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>
where
    Itype: Zero,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>: SeedableRng,
{
    /// Creates a new PCG without specifying a seed.
    /// WARNING: Every PCG created with this method will produce the same
    /// output. In most cases a seeded PCG will be more useful, please check
    /// the references for `rand::SeedableRng` and `rand::FromEntropy` for
    /// methods to seed a PCG.
    pub fn new_unseeded() -> Self {
        PcgEngine::from_seed(Default::default())
    }
}

impl<Itype, Xtype, StreamMix, MulMix, OutMix> PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>
where
    Itype: Copy + BitSize,
    Xtype: BitSize,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
{
    /// Gets the current state of the PCG Engine
    pub fn get_state(&self) -> PCGStateInfo<Itype> {
        PCGStateInfo {
            state: self.state,
            increment: self.stream_mix.increment(),
            multiplier: MulMix::multiplier(),
            internal_width: Itype::BITS,
            output_width: Xtype::BITS,
            output_mixin: OutMix::SERIALIZER_ID.into(),
        }
    }

    pub fn restore_state_with_no_verification(state: PCGStateInfo<Itype>) -> Self {
        PcgEngine {
            state: state.state,
            stream_mix: StreamMix::build(None), // FIXME
            mul_mix: PhantomData,
            out_mix: PhantomData,
            phantom: PhantomData,
        }
    }
}

impl<Itype, Xtype, MulMix, OutMix> PcgEngine<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix>
where
    Itype: Copy + Eq + Zero + BitSize,
    SpecificSeqStream<Itype>: Stream<Itype>,
    Xtype: BitSize,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
{
    // Restores a PCG from a given state and verifies that all the parameters match the recorded state
    pub fn restore_state(state: PCGStateInfo<Itype>) -> Result<Self, String> {
        if OutMix::SERIALIZER_ID != state.output_mixin {
            return Err("Output Mixin type does not match recorded state".into());
        }

        if MulMix::multiplier() != state.multiplier {
            return Err("PCG using different multiplier than recorded state".into());
        }

        if Xtype::BITS != state.output_width {
            return Err("PCG uses different output size than recorded state".into());
        }

        if Itype::BITS != state.internal_width {<commit_msg>Fixed restoring state with no verification<commit_after>/*
 * PCG Random Number Generation for Rust
 *
 * Copyright 2015 <NAME> <<EMAIL>>
 *
 * Licensed 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.
 *
 * This work is derived from the implementation PCG RNG for C++ by
 * <NAME>.
 *
 * For additional information about the PCG random number generation scheme,
 * including its license and other licensing options, visit
 *
 *     http://www.pcg-random.org
 */

//! An implementation of the PCG random family of random number generators.
//! Details about the PCG generators can be found at [pcg-random.org](http://pcg-random.org)
//!
//! Currently this library provides several PCG generators:
//!
//! * `Pcg32` : 64bit LCG with an xorshift and right rotation applied to the output. To improve
//!   security only 32bits of the state are reported as output.
//! * `Pcg32Onseq` : Same as `Pcg32` but with a fixed sequence. Useful if you don't care about having
//!   multiple streams of random numbers from the same seed.
//! * `Pcg32Unique` : Same as `Pcg32` but the sequence is set by the memory location of the RNG
//!   This means that multiple `Pcg32_unique` with the same seed will produce different sequences
//!   of numbers. *NOTE*: This means that you may not get consistant results across runs of your
//!   program. If the memory location of your PCG moves for any reason such as the state of the
//!   allocator being different you will get a different stream of numbers.
//!
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/pcg_rand) and can be used by
//! adding the `pcg_rand` crate to your projects Cargo.toml
//!
//! ```toml
//! [dependencies]
//! pcg_rand = "0.12.0"
//! ```
//! # Typename Nomenclature
//! This library attempts to simplify using the PCG generators by defining easy
//! types for use. The following attempts to help you decode these typenames
//!
//! Consider the example `OneseqXshRr6432`. This consists of 4 major parts.
//!
//! 1. First is the sequence type
//! 1. Second is the permutation function
//! 1. Third is the state size in bits
//! 1. Fourth is the output size in bits
//!
//! ## Sequence types
//!
//! This library provides the following sequence types
//!
//! * `Setseq`: This is a settable stream. The random number stream can be set manually.
//! * `Unique`: This is a unique stream. Each instance of this type will be given a unique stream
//!   that cannot be modified.
//! * `Oneseq`: This is one fixed random sequence. It is hardcoded into the library and should be
//!   good enough to give good "randomness".
//! * `Mcg`: This has no random sequence it degenerates the internal LCG into a MCG. This is for
//!   speed.
//!
//! ## Permutation functions
//!
//! There are many possible permuation functions that this library can implement. Many of them are
//! composed of several indiviual components. The components that are used are:
//!
//! * `Xsh`: Refers to a High Xorshift function.
//! * `Rr`: Refers to a random rotation. Randomly rotates based on entropy from the state.
//! * `Rs`: Refers to a random shift. Randomly shifts based on entropy from the state.
//! * 'DXsM`: Refers to the Double-Xorshift and Multiply output
//!
//! # How to Use
//! The simple generators work like the other Rng's from the `rand` crate.
//! You can create a PCG as follows
//!
//! ```
//! extern crate pcg_rand;
//! extern crate rand;
//!
//! use rand::{Rng, SeedableRng};
//! use pcg_rand::Pcg32;
//!
//! fn main() {
//!     let mut pcg = Pcg32::from_entropy();
//!
//!     let x : u32 = pcg.gen();
//! }
//! ```
//!
//! The extended generators can be built in two ways, either by creating one
//! directly, or by building them from a generator at its current state.
//!
//! ```
//! extern crate pcg_rand;
//! extern crate rand;
//!
//! use pcg_rand::{
//!     Pcg32Unique,
//!     extension::{Pcg32Ext, ExtPcg, Ext256}
//! };
//! use rand::SeedableRng;
//!
//! //Create an extended generator explicitly
//! let ext1 = Pcg32Ext::<Ext256>::from_entropy();
//!
//! //Create from another PCG
//! let ext2 : ExtPcg<_,_,_,_,_,Ext256> = ExtPcg::from_pcg(Pcg32Unique::from_entropy());
//! ```
extern crate byteorder;
extern crate num_traits;
extern crate rand;
extern crate rand_core;

#[cfg(feature = "serde1")]
extern crate serde;

use rand_core::{RngCore, SeedableRng};

use std::num::Wrapping;

pub mod extension;
pub mod multiplier;
pub mod numops;
pub mod outputmix;
pub mod seeds;
pub mod stream;

#[cfg(feature = "serde1")]
pub mod serialization;

#[cfg(feature = "serde1")]
use serde::{Deserialize, Serialize};

use multiplier::{DefaultMultiplier, McgMultiplier, Multiplier};
use num_traits::{One, Zero};
use numops::*;
use outputmix::{DXsMMixin, OutputMixin, XshRrMixin, XshRsMixin};
use seeds::PcgSeeder;
use stream::{NoSeqStream, OneSeqStream, SpecificSeqStream, Stream, UniqueSeqStream};

use std::marker::PhantomData;

/// A generic PCG structure.
///
/// This structure allows the building of many types of PCG generators by using various
/// Mixins for both the stream, multiplier, and permutation function.
pub struct PcgEngine<
    Itype,
    Xtype,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
> {
    state: Itype,
    stream_mix: StreamMix,
    mul_mix: PhantomData<MulMix>,
    out_mix: PhantomData<OutMix>,
    phantom: PhantomData<Xtype>,
}

impl<Itype, Xtype, StreamMix, MulMix, OutMix> PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>
where
    Itype: Zero,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
    PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>: SeedableRng,
{
    /// Creates a new PCG without specifying a seed.
    /// WARNING: Every PCG created with this method will produce the same
    /// output. In most cases a seeded PCG will be more useful, please check
    /// the references for `rand::SeedableRng` and `rand::FromEntropy` for
    /// methods to seed a PCG.
    pub fn new_unseeded() -> Self {
        PcgEngine::from_seed(Default::default())
    }
}

impl<Itype, Xtype, StreamMix, MulMix, OutMix> PcgEngine<Itype, Xtype, StreamMix, MulMix, OutMix>
where
    Itype: Copy + BitSize,
    Xtype: BitSize,
    StreamMix: Stream<Itype>,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
{
    /// Gets the current state of the PCG Engine
    pub fn get_state(&self) -> PCGStateInfo<Itype> {
        PCGStateInfo {
            state: self.state,
            increment: self.stream_mix.increment(),
            multiplier: MulMix::multiplier(),
            internal_width: Itype::BITS,
            output_width: Xtype::BITS,
            output_mixin: OutMix::SERIALIZER_ID.into(),
        }
    }

    pub fn restore_state_with_no_verification(state: PCGStateInfo<Itype>) -> Self {
        PcgEngine {
            state: state.state,
            stream_mix: StreamMix::build(Some(state.increment)),
            mul_mix: PhantomData,
            out_mix: PhantomData,
            phantom: PhantomData,
        }
    }
}

impl<Itype, Xtype, MulMix, OutMix> PcgEngine<Itype, Xtype, SpecificSeqStream<Itype>, MulMix, OutMix>
where
    Itype: Copy + Eq + Zero + BitSize,
    SpecificSeqStream<Itype>: Stream<Itype>,
    Xtype: BitSize,
    MulMix: Multiplier<Itype>,
    OutMix: OutputMixin<Itype, Xtype>,
{
    // Restores a PCG from a given state and verifies that all the parameters match the recorded state
    pub fn restore_state(state: PCGStateInfo<Itype>) -> Result<Self, String> {
        if OutMix::SERIALIZER_ID != state.output_mixin {
            return Err("Output Mixin type does not match recorded state".into());
        }

        if MulMix::multiplier() != state.multiplier {
            return Err("PCG using different multiplier than recorded state".into());
        }

        if Xtype::BITS != state.output_width {
            return Err("PCG uses different output size than recorded state".into());
        }

        if Itype::BITS != state.internal_width {
{'fraction_non_alphanumeric': 0.1200235224933843, 'fraction_numerical': 0.007644810349897089, 'mean_word_length': 3.2760875031430725, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 81, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '555994', 'n_tokens_mistral': 5394, 'n_tokens_neox': 5061, 'n_words': 1928}