diff --git a/.gitignore b/.gitignore index b25c15b..f05be0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *~ +libsrng/target/ +libsrng/Cargo.lock diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..21e79a5 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +install: + cp -f libsrng.so /usr/local/lib/libsrng.so + ln -sf /usr/local/lib/libsrng.so /usr/lib/libsrng.so + +uninstall: + rm -f /usr/local/lib/libsrng.so + rm /usr/lib/libsrng.so + +build: + cd libsrng && cargo build --release + cp libsrng/target/release/libsrng.so ./ + gpg --sign libsrng.so diff --git a/README b/README new file mode 100644 index 0000000..3451480 --- /dev/null +++ b/README @@ -0,0 +1,5 @@ +Prebuild binary signed with https://flanchan.moe/flanchan.asc + +To build dependencies yourself run: + make build && sudo make install +(requires Rust) diff --git a/cl-rng.asd b/cl-rng.asd index 0d832f7..cfe9b30 100644 --- a/cl-rng.asd +++ b/cl-rng.asd @@ -6,6 +6,8 @@ :license "None" :version "0.0.1" :serial t + :depends-on (:cffi) :components ((:file "package") + (:file "ffi") (:file "urandom") (:file "cl-rng"))) diff --git a/cl-rng.lisp b/cl-rng.lisp index c0a31e0..01541dc 100644 --- a/cl-rng.lisp +++ b/cl-rng.lisp @@ -2,9 +2,9 @@ (in-package :cl-rng) -(defparameter *default-precision* 100 +(defparameter *default-precision* 1 "Default precision for the default RNG provider") -(defparameter *default-randomness-provider* #'(lambda (&rest args) (apply #'urandom (append `(:precision ,*default-precision*) args))) +(defparameter *default-randomness-provider* #'(lambda (&rest args) (apply #'crandom (append `(:precision ,*default-precision*) args))) "The default randomness provider used by cl-rng functions") (defun chance (fraction &key (provider *default-randomness-provider*)) @@ -58,6 +58,7 @@ ;; Exports (export '*default-randomness-provider*) +(export '*default-precision*) (defsetf within within-set) (export 'range) (export 'within) diff --git a/crandom.lisp b/crandom.lisp new file mode 100644 index 0000000..3746c85 --- /dev/null +++ b/crandom.lisp @@ -0,0 +1,19 @@ + +(in-package #:cl-rng) + +(defun crandom (&key (limit 1.0) (precision 1) (transform nil)) + (let ((transform (or transform #'identity))) + (multiple-value-bind (result ok) (cl-rng-ffi:ffi-sample) + (and ok + (funcall transform + (* limit + (if (< precision 2) + result + (/ (apply #'+ (mapcan #'(lambda (x) + (and (not (null x)) + (list x))) + (loop for x from 0 below precision collect + (crandom)))) + precision)))))))) + +(export 'crandom) diff --git a/ffi.lisp b/ffi.lisp new file mode 100644 index 0000000..f86b79a --- /dev/null +++ b/ffi.lisp @@ -0,0 +1,19 @@ + +(in-package #:cl-rng-ffi) + +(define-foreign-library libsrng + (:unix (:or "libsrng.so" "libsrng" "./libsrng.so")) + (t (:default "libsrng"))) + +(use-foreign-library libsrng) + +(defcfun "sample" :int (to :pointer)) + +(defun ffi-sample () + (with-foreign-pointer (value 8) + (let ((rval (sample value))) + (values + (mem-ref value :double 0) + (= rval 1))))) + +(export 'ffi-sample) diff --git a/libsrng.so b/libsrng.so new file mode 100755 index 0000000..2be0346 Binary files /dev/null and b/libsrng.so differ diff --git a/libsrng.so.gpg b/libsrng.so.gpg new file mode 100644 index 0000000..bbd462f Binary files /dev/null and b/libsrng.so.gpg differ diff --git a/libsrng/Cargo.toml b/libsrng/Cargo.toml new file mode 100644 index 0000000..375aaf7 --- /dev/null +++ b/libsrng/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "srng" +version = "0.1.0" +authors = ["Avril "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +getrandom = "0.1" \ No newline at end of file diff --git a/libsrng/src/lib.rs b/libsrng/src/lib.rs new file mode 100644 index 0000000..480dbad --- /dev/null +++ b/libsrng/src/lib.rs @@ -0,0 +1,56 @@ +extern crate getrandom; + +use getrandom::*; + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn it_works() { + let mut f: f64 = 0.0; + assert_eq!(sample(&mut f as *mut f64), 1); + } +} + +fn get() -> Result +{ + let mut value: T = Default::default(); + unsafe { + let mut slice = std::slice::from_raw_parts_mut(&mut value as *mut T as *mut u8, std::mem::size_of::()); + populate(&mut slice)?; + } + + Ok(value) +} + +fn double() -> Result +{ + let long: i64 = get::()?; + + Ok( ((long & ((1i64 << 53) - 1)) as f64) * (1_f64 / ((1_i64 << 53) as f64))) +} + +fn populate(mut value: &mut [u8]) -> Result<(), Error> +{ + getrandom(&mut value)?; + + Ok(()) +} + +#[no_mangle] +pub extern "C" fn sample(value: *mut f64) -> i32 +{ + match std::panic::catch_unwind(|| { + unsafe { + match double() { + Ok(x) => *value = x, + Err(_) => return 0, + } + } + 1 + }) { + Ok(v) => v, + Err(_) => 0, + } +} + diff --git a/package.lisp b/package.lisp index 00fcf6f..bc6f8e4 100644 --- a/package.lisp +++ b/package.lisp @@ -2,3 +2,6 @@ (defpackage #:cl-rng (:use #:cl)) + +(defpackage #:cl-rng-ffi + (:use :cl :cffi :cl-rng))