2026-10-30 20:08:28 +01:00

74 lines
2.5 KiB
Clojure

;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS SUBSIDIARY SL
(ns benches.render-wasm.random
"Seeded numbers for reproducible scene construction and report resampling.
A seed is an integer from 0 through 4294967295. Each call to `create` owns a
separate Mulberry32 state. Calling the returned function advances that state
and returns a number in [0,1). Equal seeds and equal numbers of calls produce
equal sequences, including seed zero."
(:require
[app.common.types.color :as clr]
[app.common.uuid :as uuid]))
(defn seed?
"Returns true for integers from 0 through 4294967295, inclusive."
[value]
(and (integer? value) (<= 0 value 4294967295)))
(defn create
"Returns a function that draws seeded numbers from [0, 1) using Mulberry32.
Each function owns its state. A seed outside the uint32 range throws
::invalid-seed; uint32 means an integer from 0 through 4294967295."
[seed]
(when-not (seed? seed)
(throw (ex-info "random seed must be an integer in [0, 2^32)"
{:type ::invalid-seed :seed seed})))
(let [state (volatile! (bit-or seed 0))]
(fn []
(let [s (bit-or (+ @state 0x6d2b79f5) 0)
_ (vreset! state s)
v (js/Math.imul (bit-xor s (unsigned-bit-shift-right s 15))
(bit-or s 1))
v (bit-xor v (+ v (js/Math.imul (bit-xor v (unsigned-bit-shift-right v 7))
(bit-or v 61))))
v (bit-xor v (unsigned-bit-shift-right v 14))]
(/ (unsigned-bit-shift-right v 0) 4294967296)))))
(defn round3
"Rounds to 3 decimal places"
[value]
(/ (js/Math.round (* 1000 value)) 1000))
(defn rng-float
"Draws a float in `[min, max)` from the random source."
[rng min max]
(+ min (* (rng) (- max min))))
(defn rng-int
"Draws an integer in `[min, max)` from the random source."
[rng min max]
(js/Math.floor (rng-float rng min max)))
(defn rng-uuid
"Draws a deterministic uuid from two 32-bit values of the random source."
[rng]
(uuid/custom (rng-int rng 0 4294967296)
(rng-int rng 0 4294967296)))
(defn rng-hex-color
"Draws a hex color from three RGB channels in [0,256)."
[rng]
(clr/rgb->hex [(rng-int rng 0 256) (rng-int rng 0 256) (rng-int rng 0 256)]))
(defn rng-opacity
"Draws opacity in [0.1,0.999], rounded to three decimal places."
[rng]
(min 0.999 (round3 (rng-float rng 0.1 1))))