Import random-fast-rng 0.1.1 upstream upstream/0.1.1
authorRoy7Kim <myoungwoon.kim@samsung.com>
Mon, 20 Mar 2023 05:38:16 +0000 (14:38 +0900)
committerRoy7Kim <myoungwoon.kim@samsung.com>
Mon, 20 Mar 2023 05:38:16 +0000 (14:38 +0900)
.cargo_vcs_info.json [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
Cargo.toml.orig [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]
src/thread.rs [new file with mode: 0644]

diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644 (file)
index 0000000..63ea7be
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "aac0983a35a81c1b22621961a881ddd3468fae49"
+  }
+}
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..42c30a6
--- /dev/null
@@ -0,0 +1,35 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "random-fast-rng"
+version = "0.1.1"
+authors = ["Elichai Turkel <elichai.turkel@gmail.com>"]
+include = ["**/*.rs", "Cargo.toml"]
+description = "Rust library for Blazing fast non cryptographic random number generator"
+readme = "README.md"
+keywords = ["rand", "random", "random-rs", "rng"]
+categories = ["algorithms", "no-std", "development-tools::testing"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/elichai/random-rs"
+[dependencies.doc-comment]
+version = "0.3"
+optional = true
+
+[dependencies.random-trait]
+version = "0.1"
+
+[features]
+default = ["std"]
+std = []
+[badges.travis-ci]
+repository = "elichai/random-rs"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644 (file)
index 0000000..a5308b8
--- /dev/null
@@ -0,0 +1,28 @@
+[package]
+name = "random-fast-rng"
+version = "0.1.1"
+authors = ["Elichai Turkel <elichai.turkel@gmail.com>"]
+license = "MIT/Apache-2.0"
+readme = "README.md"
+description = "Rust library for Blazing fast non cryptographic random number generator"
+categories = ["algorithms", "no-std", "development-tools::testing"]
+keywords = ["rand", "random", "random-rs", "rng"]
+repository = "https://github.com/elichai/random-rs"
+
+include = [
+    "**/*.rs",
+    "Cargo.toml",
+]
+
+[dependencies]
+random-trait = { version = "0.1", path = "../random-trait" }
+
+doc-comment = { version = "0.3", optional = true }
+
+
+[features]
+default = ["std"]
+std = []
+
+[badges]
+travis-ci = { repository = "elichai/random-rs" }
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..f66b352
--- /dev/null
@@ -0,0 +1,156 @@
+#![no_std]
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+
+//! # Random-fast-rng
+//!
+//! This crate provides a fast **non cryptographic** random number generator that implements the [`Random`](trait.Random.html) trait. <br>
+//! Currently it's implemented using the `Pcg32` algorithm, that generates 32 bit of random data for every state change. <br>
+//! the exact algorithm might change in the future, but the properties should stay the same (Blazing fast, non cryptographic, and minimal I/O)
+//! The crate is part of the `random-rs` facade, and as such supports older rust compilers(currently 1.13+) and should have only thin amount of dependencies.
+//!
+//! This Random generator is good for testing uses, and use cases that require some non-determinism. it shouldn't be used to generate keys/passwords. <br>
+//!
+//! By enabling the `std` feature this crate exposes a [`new()`](struct.FastRng.html#method.new) function that uses [`SystemTime::now()`](https://doc.rust-lang.org/std/time/struct.SystemTime.html) to seed the RNG.<br>
+//! It also exposes a [`local_rng()`](fn.local_rng.html) function to give a persistent Rng that is seeded only once and is unique per thread (so there's no need to worry about dropping and reinitializing the Rng)
+//!
+
+#[cfg(feature = "std")]
+#[macro_use]
+extern crate std;
+
+#[cfg(feature = "std")]
+mod thread;
+
+pub extern crate random_trait;
+pub use random_trait::Random;
+
+#[cfg(feature = "std")]
+use thread::FromRawPtr;
+#[cfg(feature = "std")]
+pub use thread::ThreadFastRng;
+
+use core::mem;
+
+#[cfg(feature = "doc-comment")]
+extern crate doc_comment;
+#[cfg(feature = "doc-comment")]
+doc_comment::doctest!("../README.md");
+
+const PCG_DEFAULT_MULTIPLIER_64: u64 = 6_364_136_223_846_793_005;
+
+/// A FastRng struct implementing [`Random`](trait.Random.html). you can initialize it with your own seed using [`FastRng::seed()`](struct.FastRng.html#method.seed)
+/// Or if the `std` feature is enabled call [`FastRng::new()`](struct.FastRng.html#method.seed) which will seed it with the system time. <br>
+/// For ergonomics and ease of usability the Rng is also provided as a global thread local variable using [`FastRng::local_rng()`](fn.local_rng.html)
+pub struct FastRng {
+    // Pcg32
+    state: u64,
+    inc: u64,
+}
+
+impl FastRng {
+    /// Creates a new instance of `FastRng` seeded with the system time.
+    ///
+    /// # Examples
+    /// ```rust
+    /// use random_fast_rng::{FastRng, Random};
+    ///
+    /// let mut rng = FastRng::new();
+    /// let random_u8 = rng.get_u8();
+    /// let arr: [u8; 32] = rng.gen();
+    /// ```
+    ///
+    #[cfg(feature = "std")]
+    pub fn new() -> Self {
+        let (a, b) = time_seed();
+        Self::seed(a, b)
+    }
+
+    /// A function to manually seed the Rng in `no-std` cases.
+    pub fn seed(seed: u64, seq: u64) -> Self {
+        let init_inc = (seq << 1) | 1;
+        let init_state = seed + init_inc;
+        let mut rng = FastRng { state: init_state, inc: init_inc };
+        rng.state = rng.state.wrapping_mul(PCG_DEFAULT_MULTIPLIER_64).wrapping_add(rng.inc);
+        rng
+    }
+
+    fn gen_u32(&mut self) -> u32 {
+        let old_state = self.state;
+        self.state = self.state.wrapping_mul(PCG_DEFAULT_MULTIPLIER_64).wrapping_add(self.inc);
+
+        let xorshift = (((old_state >> 18) ^ old_state) >> 27) as u32;
+        let rot = (old_state >> 59) as i32;
+        (xorshift >> rot) | (xorshift << ((-rot) & 31))
+    }
+}
+
+/// Returns a thread local instance which is seeded only once per thread (no need to worry about dropping and reinitializing)
+///
+/// # Examples
+/// ```rust
+/// use random_fast_rng::{Random, local_rng};
+///
+/// let random_u8 = local_rng().get_u8();
+/// let arr: [u8; 32] = local_rng().gen();
+/// ```
+///
+#[cfg(feature = "std")]
+pub fn local_rng() -> ThreadFastRng {
+    use std::cell::RefCell;
+    thread_local! {
+        pub static THREAD_FAST_RNG: RefCell<FastRng> = RefCell::new(FastRng::new());
+    }
+    let ptr = THREAD_FAST_RNG.with(|r| r.as_ptr());
+    ThreadFastRng::from_ptr(ptr)
+}
+
+#[cfg(feature = "std")]
+fn time_seed() -> (u64, u64) {
+    use std::time;
+    let now = time::SystemTime::now();
+    let unix = now.duration_since(time::UNIX_EPOCH).unwrap();
+
+    (unix.as_secs(), u64::from(unix.subsec_nanos()))
+}
+
+impl Random for FastRng {
+    type Error = ();
+
+    fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
+        for chunk in buf.chunks_mut(4) {
+            let rand: [u8; 4] = unsafe { mem::transmute(self.gen_u32()) };
+            let len = chunk.len();
+            chunk.copy_from_slice(&rand[..len]);
+        }
+        Ok(())
+    }
+    fn get_u32(&mut self) -> u32 {
+        self.gen_u32()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_local() {
+        let mut local_rng = local_rng();
+        let a: u64 = local_rng.gen();
+        let b: u32 = local_rng.gen();
+        let c: [u8; 64] = local_rng.gen();
+        assert_ne!(a, 0);
+        assert_ne!(b, 0);
+        assert_ne!(&c[..], &[0u8; 64][..]);
+    }
+
+    #[test]
+    fn test_float() {
+        let mut rng = FastRng::new();
+        let f: f32 = rng.gen();
+        assert!(f > 0.0 && f < 1.0);
+        let f: f64 = rng.gen();
+        assert!(f > 0.0 && f < 1.0);
+    }
+}
diff --git a/src/thread.rs b/src/thread.rs
new file mode 100644 (file)
index 0000000..63a7265
--- /dev/null
@@ -0,0 +1,32 @@
+use FastRng;
+
+use core::ops::{Deref, DerefMut};
+
+/// A shim that points to the global `FastRng` instance. isn't safe for multi-threading.
+///
+/// This struct is created by [`thread_local()`](../struct.FastRng.html#method.thread_local)
+pub struct ThreadFastRng(*mut FastRng);
+
+impl Deref for ThreadFastRng {
+    type Target = FastRng;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe { &*self.0 }
+    }
+}
+
+impl DerefMut for ThreadFastRng {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe { &mut *self.0 }
+    }
+}
+
+pub trait FromRawPtr<T> {
+    fn from_ptr(ptr: *mut T) -> Self;
+}
+
+impl FromRawPtr<FastRng> for ThreadFastRng {
+    fn from_ptr(ptr: *mut FastRng) -> ThreadFastRng {
+        ThreadFastRng(ptr)
+    }
+}