1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
-- urn class: random selection without repetitions.
-- fbar 2007
-- urn interface:
local urn = {}
function urn.new(size)
assert(size > 0, "Error: size of urn must be greater than 0")
local t = {size=size, last=size}
for i=1,size do
t[i] = i
end
return t
end
function urn.get(u)
if u.last > 0 then
local i = math.random(u.last)
local res = u[i]
u[i] = u[u.last]
u.last = u.last - 1
return res
else
return nil
end
end
function urn.reset(u)
u.last = u.size
for i=1,u.size do
u[i] = i
end
end
-- Pd class:
local M = pd.Class:new():register("lurn")
function M:initialize(name, atoms)
if type(atoms[1]) == "number" and atoms[1] >= 1 then
self.u = urn.new(math.floor(math.max(atoms[1]), 1))
else
self.u = urn.new(1)
end
self.inlets = 2
self.outlets = 2
return true
end
function M:finalize()
self.u = nil
end
function M:in_2_float(f)
if f >= 1 then
self.u = urn.new(math.floor(f))
else
self:error("size of urn too small. needs to be 1 at least")
end
end
function M:in_1_clear(atoms)
urn.reset(self.u)
end
function M:in_1_seed(atoms)
if type(atoms[1]) == "number" then
math.randomseed(atoms[1])
else
self:error("seed needs a number")
end
end
function M:in_1_bang()
local f = urn.get(self.u)
if type(f) == "number" then
self:outlet(1, "float", {f - 1})
else
self:outlet(2, "bang", {})
end
end
|