Skip to content

Instantly share code, notes, and snippets.

@tsulej
Last active June 15, 2016 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsulej/34a230f9d3bbf89fd618901f19b14723 to your computer and use it in GitHub Desktop.
Save tsulej/34a230f9d3bbf89fd618901f19b14723 to your computer and use it in GitHub Desktop.
Wrapper for RNGs from Apache Math
(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