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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
import Constant, Error, Op, Input, T, Array, sig, evt from require 'alv.base'
vec2 = Array 2, T.num
apply_range = (range, val) ->
if range\type! == T.str
switch range!
when 'uni' then val
when 'bip' then val*2 - 1
when 'rad' then val*2 * math.pi
when 'deg' then val * 360
else
error Error 'argument', "unknown range '#{range!}'"
elseif range\type! == T.num
val * range!
elseif range\type! == vec2
{ min, max } = range!
min + val * (max - min)
else
error Error 'argument', "range has to be a string or number"
range_doc = "
range can be one of:
- 'uni' [ 0 - 1[ (default)
- 'bip' [-1 - 1[
- 'rad' [ 0 - tau[
- 'deg' [ 0 - 360[
- (num) [ 0 - num[
- [min max]"
pattern = -evt.bang + -(sig.num / sig.str / sig[vec2])
num = Constant.meta
meta:
name: 'num'
summary: 'Generate a random number.'
examples: { '(random/num [trigger] [range]))' }
description: "Generate a random value in `range` when created and on `trig`.
#{range_doc}"
value: class extends Op
new: (...) =>
super ...
@setup_out '~', T.num
@state or @gen!
gen: => @state = math.random!
setup: (inputs) =>
{ trig, range } = pattern\match inputs
super
trig: trig and Input.hot trig
range: Input.hot range or Constant.str 'uni'
tick: =>
@gen! if @inputs.trig and @inputs.trig\dirty!
@out\set apply_range @inputs.range, @state
vec = (n) ->
typ = Array n, T.num
Constant.meta
meta:
name: "vec#{n}"
summary: 'Generate a random vector.'
examples: { '(random/vec#{n} [trigger] [range]))' }
description: "Generate a random #{typ} in `range` when created and on `trig`.
#{range_doc}"
value: class extends Op
new: (...) =>
super ...
@setup_out '~', typ
@state or @gen!
gen: => @state = for i=1,n do math.random!
setup: (inputs) =>
{ trig, range } = pattern\match inputs
super
trig: trig and Input.hot trig
range: Input.hot range or Constant.str 'uni'
tick: =>
@gen! if @inputs.trig and @inputs.trig\dirty!
@out\set [apply_range @inputs.range, v for v in *@state]
int = Constant.meta
meta:
name: 'int'
summary: 'Generate a random integer.'
examples: { '(random/num [trigger] [min] max))' }
description: "Generate a random value in `range` when created and on `trig`.
#{range_doc}"
value: class extends Op
new: (...) =>
super ...
@setup_out '~', T.num
@state or @gen!
gen: => @state = math.random!
int_pattern = -evt.bang + sig.num + -sig.num
setup: (inputs) =>
{ trig, min, max } = int_pattern\match inputs
if not max
min, max = nil, min
super
trig: trig and Input.hot trig
min: Input.hot min or Constant.num 0
max: Input.hot max
tick: =>
{ :trig, :max, :min } = @unwrap_all!
if trig
last = math.floor min + (max - min) * @state
while last == math.floor min + (max - min) * @state
@gen!
@out\set math.floor min + (max - min) * @state
Constant.meta
meta:
name: 'random'
summary: "Random number generation."
value:
:num
:int
vec2: vec 2
vec3: vec 3
vec4: vec 4
|