Last active
June 15, 2016 21:03
-
-
Save tsulej/34a230f9d3bbf89fd618901f19b14723 to your computer and use it in GitHub Desktop.
Wrapper for RNGs from Apache Math
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns g2d.utils.random | |
(:import [org.apache.commons.math3.random RandomGenerator ISAACRandom JDKRandomGenerator MersenneTwister | |
Well512a Well1024a Well19937a Well19937c Well44497a Well44497b])) | |
(set! *warn-on-reflection* true) | |
(defmacro next-random-value-fn | |
"generate function for next random value (long, int, double, gaussian) with scale and shift" | |
[func int?] | |
(let [r (vary-meta (gensym "r") assoc :tag 'RandomGenerator) | |
mx2 (gensym "mx2") | |
mn (gensym "mn") | |
mx (gensym "mx")] | |
`(fn self# | |
([~r] (~func ~r)) | |
([~r ~mx2] | |
~(if int? | |
`(mod (~func ~r) ~mx2) | |
`(* ~mx2 (~func ~r)))) | |
([~r ~mn ~mx] | |
(let [diff# (- ~mx ~mn)] | |
(+ ~mn (self# ~r diff#))))))) | |
(defprotocol Randomizer | |
(irand [t] [t mx] [t mn mx] "int random") | |
(drand [t] [t mx] [t mn mx] "double random") | |
(lrand [t] [t mx] [t mn mx] "long random") | |
(frand [t] [t mx] [t mn mx] "float random") | |
(grand [t] [t std] [t avg std] "gaussian random") | |
(brand [t] [t thr] "boolean random, with probability option")) | |
(def next-gaussian (next-random-value-fn .nextGaussian false)) | |
(defn next-random-with-probability | |
"" | |
[^RandomGenerator r thr] | |
(< (drand r) thr)) | |
(extend RandomGenerator | |
Randomizer | |
{:irand (next-random-value-fn .nextInt true) | |
:lrand (next-random-value-fn .nextLong true) | |
:frand (next-random-value-fn .nextFloat false) | |
:drand (next-random-value-fn .nextDouble false) | |
:grand (fn | |
([^RandomGenerator t] (next-gaussian t)) | |
([^RandomGenerator t std] (next-gaussian t std)) | |
([^RandomGenerator t avg std] (next-gaussian t avg (+ avg std)))) | |
:brand (fn | |
([^RandomGenerator t] (.nextBoolean t)) | |
([^RandomGenerator t thr] (next-random-with-probability t thr)))}) | |
(defmacro create-object-with-seed | |
"create object of the class with (or not) given seed" | |
[cl seed] | |
`(if-let [arg# ~seed] | |
(new ~cl (int arg#)) | |
(new ~cl))) | |
(defmulti make-randomizer (fn [m & _] m)) | |
(defmethod make-randomizer :mersenne [m & [seed]] | |
(create-object-with-seed MersenneTwister seed)) | |
(defmethod make-randomizer :isaac [m & [seed]] | |
(create-object-with-seed ISAACRandom seed)) | |
(defmethod make-randomizer :well512 [m & [seed]] | |
(create-object-with-seed Well512a seed)) | |
(defmethod make-randomizer :well1024 [m & [seed]] | |
(create-object-with-seed Well1024a seed)) | |
(defmethod make-randomizer :well19937a [m & [seed]] | |
(create-object-with-seed Well19937a seed)) | |
(defmethod make-randomizer :well19937c [m & [seed]] | |
(create-object-with-seed Well19937c seed)) | |
(defmethod make-randomizer :well44497a [m & [seed]] | |
(create-object-with-seed Well44497a seed)) | |
(defmethod make-randomizer :well44497b [m & [seed]] | |
(create-object-with-seed Well44497b seed)) | |
(defmethod make-randomizer :default [m & [seed]] | |
(create-object-with-seed JDKRandomGenerator seed)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment