redshift 1.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. data/.gitignore +8 -0
  2. data/README +5 -0
  3. data/RELEASE-NOTES +455 -0
  4. data/TODO +431 -0
  5. data/bench/alg-state.rb +61 -0
  6. data/bench/bench +26 -0
  7. data/bench/bench.rb +10 -0
  8. data/bench/continuous.rb +76 -0
  9. data/bench/diff-bench +86 -0
  10. data/bench/discrete.rb +101 -0
  11. data/bench/euler.rb +50 -0
  12. data/bench/formula.rb +78 -0
  13. data/bench/half-strict.rb +103 -0
  14. data/bench/inertness.rb +116 -0
  15. data/bench/queue.rb +92 -0
  16. data/bench/run +66 -0
  17. data/bench/simple.rb +74 -0
  18. data/bench/strictness.rb +86 -0
  19. data/examples/ball-tkar.rb +72 -0
  20. data/examples/ball.rb +123 -0
  21. data/examples/collide.rb +70 -0
  22. data/examples/connect-parallel.rb +48 -0
  23. data/examples/connect.rb +109 -0
  24. data/examples/constants.rb +27 -0
  25. data/examples/delay.rb +80 -0
  26. data/examples/derivative.rb +77 -0
  27. data/examples/euler.rb +46 -0
  28. data/examples/external-lib.rb +33 -0
  29. data/examples/guard-debugger.rb +77 -0
  30. data/examples/lotka-volterra.rb +33 -0
  31. data/examples/persist-ball.rb +68 -0
  32. data/examples/pid.rb +87 -0
  33. data/examples/ports.rb +60 -0
  34. data/examples/queue.rb +56 -0
  35. data/examples/queue2.rb +98 -0
  36. data/examples/reset-with-event-val.rb +28 -0
  37. data/examples/scheduler.rb +104 -0
  38. data/examples/set-dest.rb +23 -0
  39. data/examples/simulink/README +1 -0
  40. data/examples/simulink/delay.mdl +827 -0
  41. data/examples/simulink/derivative.mdl +655 -0
  42. data/examples/step-discrete-profiler.rb +103 -0
  43. data/examples/subsystem.rb +109 -0
  44. data/examples/sync-deadlock.rb +32 -0
  45. data/examples/sync-queue.rb +91 -0
  46. data/examples/sync-retry.rb +20 -0
  47. data/examples/sync.rb +51 -0
  48. data/examples/thermostat.rb +53 -0
  49. data/examples/zeno.rb +53 -0
  50. data/lib/accessible-index.rb +47 -0
  51. data/lib/redshift.rb +1 -0
  52. data/lib/redshift/component.rb +412 -0
  53. data/lib/redshift/meta.rb +183 -0
  54. data/lib/redshift/mixins/zeno-debugger.rb +69 -0
  55. data/lib/redshift/port.rb +57 -0
  56. data/lib/redshift/queue.rb +104 -0
  57. data/lib/redshift/redshift.rb +111 -0
  58. data/lib/redshift/state.rb +31 -0
  59. data/lib/redshift/syntax.rb +558 -0
  60. data/lib/redshift/target/c.rb +37 -0
  61. data/lib/redshift/target/c/component-gen.rb +1303 -0
  62. data/lib/redshift/target/c/flow-gen.rb +325 -0
  63. data/lib/redshift/target/c/flow/algebraic.rb +85 -0
  64. data/lib/redshift/target/c/flow/buffer.rb +74 -0
  65. data/lib/redshift/target/c/flow/delay.rb +203 -0
  66. data/lib/redshift/target/c/flow/derivative.rb +101 -0
  67. data/lib/redshift/target/c/flow/euler.rb +67 -0
  68. data/lib/redshift/target/c/flow/expr.rb +113 -0
  69. data/lib/redshift/target/c/flow/rk4.rb +80 -0
  70. data/lib/redshift/target/c/library.rb +85 -0
  71. data/lib/redshift/target/c/world-gen.rb +1370 -0
  72. data/lib/redshift/target/spec.rb +34 -0
  73. data/lib/redshift/world.rb +300 -0
  74. data/rakefile +37 -0
  75. data/test/test.rb +52 -0
  76. data/test/test_buffer.rb +58 -0
  77. data/test/test_connect.rb +242 -0
  78. data/test/test_connect_parallel.rb +47 -0
  79. data/test/test_connect_strict.rb +135 -0
  80. data/test/test_constant.rb +74 -0
  81. data/test/test_delay.rb +145 -0
  82. data/test/test_derivative.rb +48 -0
  83. data/test/test_discrete.rb +592 -0
  84. data/test/test_discrete_isolated.rb +92 -0
  85. data/test/test_exit.rb +59 -0
  86. data/test/test_flow.rb +200 -0
  87. data/test/test_flow_link.rb +288 -0
  88. data/test/test_flow_sub.rb +100 -0
  89. data/test/test_flow_trans.rb +292 -0
  90. data/test/test_inherit.rb +127 -0
  91. data/test/test_inherit_event.rb +74 -0
  92. data/test/test_inherit_flow.rb +139 -0
  93. data/test/test_inherit_link.rb +65 -0
  94. data/test/test_inherit_setup.rb +56 -0
  95. data/test/test_inherit_state.rb +66 -0
  96. data/test/test_inherit_transition.rb +168 -0
  97. data/test/test_numerics.rb +34 -0
  98. data/test/test_queue.rb +90 -0
  99. data/test/test_queue_alone.rb +115 -0
  100. data/test/test_reset.rb +209 -0
  101. data/test/test_setup.rb +119 -0
  102. data/test/test_strict_continuity.rb +410 -0
  103. data/test/test_strict_reset_error.rb +30 -0
  104. data/test/test_strictness_error.rb +32 -0
  105. data/test/test_sync.rb +185 -0
  106. data/test/test_world.rb +328 -0
  107. metadata +204 -0
@@ -0,0 +1,203 @@
1
+ module RedShift; class DelayFlow
2
+ def flow_wrapper cl, state
3
+ var_name = @var
4
+ flow = self
5
+ flow_name = "flow_#{CGenerator.make_c_name cl.name}_#{var_name}_#{state}"
6
+ delay_by = @delay_by
7
+
8
+ Component::FlowWrapper.make_subclass flow_name do
9
+ @inspect_str =
10
+ "#{cl.name}:#{state}: " +
11
+ "#{var_name} = #{flow.formula} [delay: #{delay_by}]"
12
+
13
+ ssn = cl.shadow_struct.name
14
+ cont_state_ssn = cl.cont_state_class.shadow_struct.name
15
+
16
+ require "redshift/target/c/flow/buffer"
17
+ RedShift.library.define_buffer
18
+
19
+ bufname = "#{var_name}_buffer_data"
20
+ offsetname = "#{var_name}_buffer_offset"
21
+ delayname = "#{var_name}_delay"
22
+ tsname = "#{var_name}_time_step"
23
+
24
+ cl.class_eval do
25
+ shadow_attr_accessor bufname => "Buffer #{bufname}"
26
+ shadow_attr_accessor offsetname => "long #{offsetname}"
27
+ shadow_attr_accessor delayname => "double #{delayname}"
28
+ # delay should be set only using the expr designated in :by => "expr"
29
+ shadow_attr tsname => "double #{tsname}"
30
+
31
+ after_commit do
32
+ alias_method "__#{bufname}=", "#{bufname}="
33
+ define_method "#{bufname}=" do |val|
34
+ send("__#{bufname}=", val)
35
+ d = world.time_step * (val.size / 4)
36
+ send("#{delayname}=", d) # keep cached delay consistent
37
+ end
38
+ end
39
+ private :"#{delayname}="
40
+ end
41
+
42
+ # We need the struct
43
+ shadow_library_source_file.include(cl.shadow_library_include_file)
44
+
45
+ shadow_library_source_file.define(flow_name).instance_eval do
46
+ arguments "ComponentShadow *comp_shdw"
47
+ declare :shadow => %{
48
+ struct #{ssn} *shadow;
49
+ struct #{cont_state_ssn} *cont_state;
50
+
51
+ ContVar *var;
52
+ double *ptr;
53
+ long i, len, offset, steps;
54
+ double delay, fill;
55
+ }
56
+ setup :shadow => %{
57
+ shadow = (#{ssn} *)comp_shdw;
58
+ cont_state = (#{cont_state_ssn} *)shadow->cont_state;
59
+ var = &cont_state->#{var_name};
60
+ }
61
+ setup :rk_level => %{
62
+ shadow->world->rk_level--;
63
+ } # has to happen before referenced alg flows are called in other setups
64
+
65
+ setup :delay =>
66
+ begin
67
+ "delay = #{Float(delay_by)}"
68
+ rescue ArgumentError
69
+ flow.translate(self, "delay", 0, cl, delay_by)
70
+ end
71
+
72
+ include World.shadow_library_include_file
73
+
74
+ # Note: cases 1,2 must proceed to allow alg deps to be computed,
75
+ # since their values are used later.
76
+ body %{
77
+ switch (shadow->world->rk_level) {
78
+ case 0:
79
+ ptr = shadow->#{bufname}.ptr;
80
+ offset = shadow->#{offsetname};
81
+
82
+ if (shadow->world->time_step != shadow->#{tsname}) {
83
+ if (shadow->#{tsname} == 0.0)
84
+ shadow->#{tsname} = shadow->world->time_step;
85
+ else
86
+ rs_raise(#{declare_class RedShiftError}, shadow->self,
87
+ "Delay flow doesn't support changing time_step yet"); // ##
88
+ }
89
+
90
+ if (ptr && delay == shadow->#{delayname}) {
91
+ len = shadow->#{bufname}.len;
92
+ if (offset < 0 || offset > len - 4) {
93
+ rs_raise(#{declare_class RedShiftError}, shadow->self,
94
+ "Offset out of bounds: %d not in 0..%d!", offset, len - 4);
95
+ }
96
+ }
97
+ else {
98
+ steps = floor(delay / shadow->world->time_step + 0.5);
99
+ if (steps <= 0) {
100
+ rs_raise(#{declare_class RedShiftError}, shadow->self,
101
+ "Delay too small: %f.", delay);
102
+ }
103
+ len = steps*4;
104
+
105
+ if (!ptr) {
106
+ #{flow.translate(self, "fill", 0, cl).join("
107
+ ")};
108
+
109
+ ptr = ALLOC_N(double, len);
110
+ shadow->#{bufname}.ptr = ptr;
111
+ shadow->#{bufname}.len = len;
112
+ shadow->#{offsetname} = 0;
113
+ shadow->#{delayname} = delay;
114
+
115
+ for (i=0; i<len; i++) {
116
+ ptr[i] = fill;
117
+ }
118
+ }
119
+ else { // # delay != shadow->#{delayname}
120
+ long old_len = shadow->#{bufname}.len;
121
+ double *dst, *src;
122
+
123
+ if (delay < shadow->#{delayname}) {
124
+ if (offset < len) {
125
+ dst = ptr + offset;
126
+ src = ptr + offset + old_len - len;
127
+ }
128
+ else {
129
+ dst = ptr;
130
+ src = ptr + offset - len;
131
+ offset = 0;
132
+ }
133
+ memmove(dst, src, (len - offset) * sizeof(double));
134
+ REALLOC_N(ptr, double, len);
135
+ // ## maybe better: don't release space, just use less of it
136
+ }
137
+ else { // # delay > shadow->#{delayname}
138
+ REALLOC_N(ptr, double, len);
139
+
140
+ fill = ptr[offset];
141
+ dst = ptr + offset + len - old_len;
142
+ src = ptr + offset;
143
+ memmove(dst, src, (old_len - offset) * sizeof(double));
144
+
145
+ for (i = 0; i < len - old_len; i++) {
146
+ ptr[offset + i] = fill;
147
+ }
148
+ }
149
+
150
+ shadow->#{bufname}.ptr = ptr;
151
+ shadow->#{bufname}.len = len;
152
+ shadow->#{offsetname} = offset;
153
+ shadow->#{delayname} = delay;
154
+ }
155
+ }
156
+
157
+ offset = (offset + 4) % len;
158
+ shadow->#{offsetname} = offset;
159
+
160
+ var->value_0 = ptr[offset];
161
+ var->value_1 = ptr[offset + 1];
162
+ var->value_2 = ptr[offset + 2];
163
+ var->value_3 = ptr[offset + 3];
164
+
165
+ #{flow.translate(self, "ptr[offset]", 0, cl).join("
166
+ ")};
167
+ break;
168
+
169
+ case 1:
170
+ case 2:
171
+ break;
172
+
173
+ case 3:
174
+ ptr = shadow->#{bufname}.ptr;
175
+ len = shadow->#{bufname}.len;
176
+ offset = shadow->#{offsetname};
177
+
178
+ #{flow.translate(self, "ptr[offset+1]", 1, cl).join("
179
+ ")};
180
+ #{flow.translate(self, "ptr[offset+2]", 2, cl).join("
181
+ ")};
182
+ #{flow.translate(self, "ptr[offset+3]", 3, cl).join("
183
+ ")};
184
+
185
+ var->value_0 = ptr[(offset + 4) % len];
186
+ break;
187
+
188
+ default:
189
+ rb_raise(#{declare_class RuntimeError},
190
+ "Bad rk_level, %d!", shadow->world->rk_level);
191
+ }
192
+
193
+ shadow->world->rk_level++;
194
+ var->rk_level = shadow->world->rk_level;
195
+ }
196
+ end
197
+
198
+ define_c_method :calc_function_pointer do
199
+ body "shadow->flow = &#{flow_name}"
200
+ end
201
+ end
202
+ end
203
+ end; end
@@ -0,0 +1,101 @@
1
+ module RedShift; class DerivativeFlow
2
+ def flow_wrapper cl, state
3
+ var_name = @var
4
+ flow = self
5
+ flow_name = "flow_#{CGenerator.make_c_name cl.name}_#{var_name}_#{state}"
6
+ feedback = @feedback
7
+
8
+ Component::FlowWrapper.make_subclass flow_name do
9
+ @inspect_str = "#{cl.name}:#{state}: #{var_name} = #{flow.formula}'"
10
+
11
+ ssn = cl.shadow_struct.name
12
+ cont_state_ssn = cl.cont_state_class.shadow_struct.name
13
+
14
+ # We need the struct
15
+ shadow_library_source_file.include(cl.shadow_library_include_file)
16
+
17
+ init_rhs_name = "#{var_name}_init_rhs"
18
+ cl.class_eval do
19
+ shadow_attr_accessor init_rhs_name => "double #{init_rhs_name}"
20
+ end
21
+
22
+ shadow_library_source_file.define(flow_name).instance_eval do
23
+ arguments "ComponentShadow *comp_shdw"
24
+ declare :shadow => %{
25
+ struct #{ssn} *shadow;
26
+ struct #{cont_state_ssn} *cont_state;
27
+ ContVar *var;
28
+ double antiddt, *scratch;
29
+ double time_step;
30
+ }
31
+ setup :shadow => %{
32
+ shadow = (#{ssn} *)comp_shdw;
33
+ cont_state = (#{cont_state_ssn} *)shadow->cont_state;
34
+ var = &cont_state->#{var_name};
35
+ scratch = &shadow->#{init_rhs_name};
36
+ time_step = shadow->world->time_step;
37
+ }
38
+ setup :rk_level => %{
39
+ shadow->world->rk_level--;
40
+ } # has to happen before referenced alg flows are called in other setups
41
+ if feedback ## possible to unite these cases somehow?
42
+ body %{
43
+ switch (shadow->world->rk_level) {
44
+ case 0:
45
+ #{flow.translate(self, "antiddt", 0, cl).join("
46
+ ")};
47
+ var->value_0 = var->value_1 =
48
+ var->value_2 = var->value_3 =
49
+ (antiddt - *scratch) / time_step;
50
+ *scratch = antiddt;
51
+ }
52
+ shadow->world->rk_level++;
53
+ var->rk_level = shadow->world->rk_level;
54
+ }
55
+ else
56
+ body %{
57
+ switch (shadow->world->rk_level) {
58
+ case 0:
59
+ #{flow.translate(self, "antiddt", 0, cl).join("
60
+ ")};
61
+ var->value_1 = var->value_0;
62
+ *scratch = antiddt;
63
+ break;
64
+
65
+ case 1:
66
+ #{flow.translate(self, "antiddt", 1, cl).join("
67
+ ")};
68
+ var->value_2 = (antiddt - *scratch) / (time_step/2);
69
+ *scratch = antiddt;
70
+ break;
71
+
72
+ case 2:
73
+ #{flow.translate(self, "antiddt", 2, cl).join("
74
+ ")};
75
+ var->value_3 = (antiddt - *scratch) / (time_step/2);
76
+ break;
77
+
78
+ case 3:
79
+ #{flow.translate(self, "antiddt", 3, cl).join("
80
+ ")};
81
+ var->value_0 = (antiddt - *scratch) / (time_step/2);
82
+ break;
83
+
84
+ default:
85
+ rb_raise(#{declare_class RuntimeError},
86
+ "Bad rk_level, %d!", shadow->world->rk_level);
87
+ }
88
+
89
+ shadow->world->rk_level++;
90
+ var->rk_level = shadow->world->rk_level;
91
+ }
92
+ end
93
+ end
94
+
95
+ define_c_method :calc_function_pointer do
96
+ body "shadow->flow = &#{flow_name}"
97
+ end
98
+ end
99
+ end
100
+
101
+ end; end
@@ -0,0 +1,67 @@
1
+ module RedShift; class EulerDifferentialFlow
2
+ def flow_wrapper cl, state
3
+ var_name = @var
4
+ flow = self
5
+
6
+ flow_name = "flow_#{CGenerator.make_c_name cl.name}_#{var_name}_#{state}"
7
+
8
+ Component::FlowWrapper.make_subclass flow_name do
9
+ @inspect_str = "#{cl.name}:#{state}: #{var_name} = #{flow.formula}"
10
+
11
+ ssn = cl.shadow_struct.name
12
+ cont_state_ssn = cl.cont_state_class.shadow_struct.name
13
+
14
+ # We need the struct
15
+ shadow_library_source_file.include(cl.shadow_library_include_file)
16
+
17
+ shadow_library_source_file.define(flow_name).instance_eval do
18
+ arguments "ComponentShadow *comp_shdw"
19
+ declare :shadow => %{
20
+ struct #{ssn} *shadow;
21
+ struct #{cont_state_ssn} *cont_state;
22
+ ContVar *var;
23
+ double ddt_#{var_name};
24
+ double time_step;
25
+ }
26
+ setup :first => %{
27
+ if (comp_shdw->world->rk_level == 2 ||
28
+ comp_shdw->world->rk_level == 3)
29
+ return;
30
+ } ## optimization: in rk_level==4 case, don't need to calc deps
31
+ setup :shadow => %{
32
+ shadow = (#{ssn} *)comp_shdw;
33
+ cont_state = (#{cont_state_ssn} *)shadow->cont_state;
34
+ var = &cont_state->#{var_name};
35
+ time_step = shadow->world->time_step;
36
+ } # return is necessary--else shadow, cont_state, var are uninitialized
37
+ setup :rk_level => %{
38
+ shadow->world->rk_level--;
39
+ } # has to happen before referenced alg flows are called in other setups
40
+ body %{
41
+ switch (shadow->world->rk_level) {
42
+ case 0:
43
+ #{flow.translate(self, "ddt_#{var_name}", 0, cl).join("
44
+ ")};
45
+
46
+ var->value_1 = var->value_2 =
47
+ var->value_0 + ddt_#{var_name} * time_step/2;
48
+ var->value_3 =
49
+ var->value_0 + ddt_#{var_name} * time_step;
50
+ var->rk_level = 3;
51
+ break;
52
+
53
+ case 3:
54
+ var->value_0 = var->value_3;
55
+ var->rk_level = 4;
56
+ break;
57
+ }
58
+
59
+ shadow->world->rk_level++;
60
+ }
61
+ end
62
+ define_c_method :calc_function_pointer do
63
+ body "shadow->flow = &#{flow_name}"
64
+ end
65
+ end
66
+ end
67
+ end; end
@@ -0,0 +1,113 @@
1
+ module RedShift; class CexprGuard
2
+
3
+ def initialize f
4
+ super nil, f
5
+ end
6
+
7
+ @@serial = 0
8
+
9
+ # +cl+ is the component class
10
+ ## maybe all these methods should just be called wrapper?
11
+ def guard_wrapper cl
12
+ guard = self
13
+ cl_cname = CGenerator.make_c_name cl.name
14
+ g_cname = "Guard_#{@@serial}"; @@serial += 1
15
+ guard_name = "guard_#{cl_cname}_#{g_cname}"
16
+
17
+ Component::GuardWrapper.make_subclass guard_name do
18
+ @inspect_str = "#{cl.name}: #{guard.formula}"
19
+
20
+ ssn = cl.shadow_struct.name
21
+ cont_state_ssn = cl.cont_state_class.shadow_struct.name
22
+
23
+ # We need the struct
24
+ shadow_library_source_file.include(cl.shadow_library_include_file)
25
+
26
+ strict = false
27
+
28
+ shadow_library_source_file.define(guard_name).instance_eval do
29
+ arguments "ComponentShadow *comp_shdw"
30
+ return_type "int"
31
+ declare :shadow => %{
32
+ struct #{ssn} *shadow;
33
+ struct #{cont_state_ssn} *cont_state;
34
+ ContVar *var;
35
+ }
36
+ setup :shadow => %{
37
+ shadow = (#{ssn} *)comp_shdw;
38
+ cont_state = (#{cont_state_ssn} *)shadow->cont_state;
39
+ }
40
+ declare :result => "int result"
41
+ translation = guard.translate(self, "result", 0, cl) {|s| strict = s}
42
+ body %{
43
+ #{translation.join("
44
+ ")};
45
+ return result;
46
+ }
47
+ end
48
+
49
+ @strict = strict
50
+ ## should set guard.strict = strict too?
51
+
52
+ define_c_method :calc_function_pointer do
53
+ body "shadow->guard = &#{guard_name}"
54
+ end
55
+ end
56
+ end
57
+ end; end
58
+
59
+ module RedShift; class Expr
60
+ attr_reader :type
61
+
62
+ def initialize f, type = "double"
63
+ super nil, f
64
+ @type = type
65
+ end
66
+
67
+ @@serial = 0
68
+
69
+ # +cl+ is the component class
70
+ def wrapper(cl)
71
+ expr = self
72
+ cl_cname = CGenerator.make_c_name cl.name
73
+ ex_cname = "Expr_#{@@serial}"; @@serial += 1
74
+ expr_name = "expr_#{cl_cname}_#{ex_cname}"
75
+
76
+ Component::ExprWrapper.make_subclass expr_name do
77
+ @inspect_str = "#{cl.name}: #{expr.formula}"
78
+
79
+ ssn = cl.shadow_struct.name
80
+ cont_state_ssn = cl.cont_state_class.shadow_struct.name
81
+
82
+ # We need the struct
83
+ shadow_library_source_file.include(cl.shadow_library_include_file)
84
+
85
+ shadow_library_source_file.define(expr_name).instance_eval do
86
+ arguments "ComponentShadow *comp_shdw"
87
+ return_type expr.type
88
+ declare :shadow => %{
89
+ struct #{ssn} *shadow;
90
+ struct #{cont_state_ssn} *cont_state;
91
+ ContVar *var;
92
+ }
93
+ setup :shadow => %{
94
+ shadow = (#{ssn} *)comp_shdw;
95
+ cont_state = (#{cont_state_ssn} *)shadow->cont_state;
96
+ }
97
+ declare :result => "#{expr.type} result"
98
+ translation = expr.translate(self, "result", 0, cl)
99
+ body %{
100
+ #{translation.join("
101
+ ")};
102
+ return result;
103
+ }
104
+ end
105
+
106
+ define_c_method :calc_function_pointer do
107
+ body "shadow->expr = &#{expr_name}"
108
+ end
109
+ end
110
+ end
111
+ end; end
112
+
113
+ module RedShift; class ResetExpr < Expr; end; end