redshift 1.3.17 → 1.3.18

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 (44) hide show
  1. data/.bnsignore +23 -0
  2. data/.gitignore +7 -6
  3. data/README +22 -4
  4. data/RELEASE-NOTES +16 -0
  5. data/examples/lotka-volterra.rb +1 -1
  6. data/examples/modular-component-def.rb +49 -0
  7. data/examples/robots/README +49 -0
  8. data/examples/robots/lib/base.rb +38 -0
  9. data/examples/robots/lib/explosion.rb +48 -0
  10. data/examples/robots/lib/missile.rb +75 -0
  11. data/examples/robots/lib/radar.rb +56 -0
  12. data/examples/robots/lib/robot.rb +105 -0
  13. data/examples/robots/lib/shell-world.rb +167 -0
  14. data/examples/robots/lib/tracker.rb +16 -0
  15. data/examples/robots/robots.rb +53 -0
  16. data/examples/shell.rb +1 -2
  17. data/ext/redshift/buffer/buffer.c +102 -0
  18. data/ext/redshift/buffer/buffer.h +17 -0
  19. data/ext/redshift/buffer/dir.rb +1 -0
  20. data/ext/redshift/buffer/extconf.rb +2 -0
  21. data/ext/redshift/util/isaac/extconf.rb +2 -0
  22. data/ext/redshift/util/isaac/isaac.c +129 -0
  23. data/ext/redshift/util/isaac/rand.c +140 -0
  24. data/ext/redshift/util/isaac/rand.h +61 -0
  25. data/lib/redshift/mixins/shell.rb +72 -0
  26. data/lib/redshift/redshift.rb +1 -1
  27. data/lib/redshift/syntax.rb +12 -5
  28. data/lib/redshift/target/c/component-gen.rb +11 -8
  29. data/lib/redshift/target/c/flow/buffer.rb +17 -126
  30. data/lib/redshift/target/c/flow/delay.rb +5 -5
  31. data/lib/redshift/target/c/library.rb +12 -1
  32. data/lib/redshift/util/histogram.rb +1 -1
  33. data/lib/redshift/util/irb-shell.rb +81 -0
  34. data/lib/redshift/util/isaac.rb +22 -0
  35. data/lib/redshift/util/modular.rb +48 -0
  36. data/lib/redshift/util/tkar-driver.rb +1 -2
  37. data/lib/redshift/util/tracer/var.rb +1 -1
  38. data/lib/redshift/world.rb +9 -3
  39. data/rakefile +9 -1
  40. data/test/test.rb +23 -9
  41. data/test/test_buffer.rb +1 -1
  42. data/test/test_flow_trans.rb +3 -20
  43. metadata +50 -46
  44. data/lib/redshift/mixins/irb-shell.rb +0 -151
@@ -0,0 +1,167 @@
1
+ require 'redshift/mixins/shell'
2
+ require 'redshift/util/plot'
3
+
4
+ # Adds an interactive ruby shell with plotting and animation commands.
5
+ module ShellWorld
6
+ include RedShift::Shell
7
+
8
+ def entered
9
+ @entered ||= []
10
+ end
11
+
12
+ def exited
13
+ @exited ||= []
14
+ end
15
+
16
+ def main_loop_with_shell_and_tk(argv=[])
17
+ if argv.delete "-h"
18
+ puts <<-END
19
+
20
+ -s start in shell
21
+ (otherwise, run until ^C breaks into shell)
22
+
23
+ -t start with tk animation
24
+ (otherwise, run without tk until the "tk" command)
25
+
26
+ END
27
+
28
+ exit
29
+ end
30
+
31
+ puts "^C to break into shell; 'help' for shell help"
32
+ tk if argv.delete "-t"
33
+ shell.run if argv.delete "-s"
34
+
35
+ loop do
36
+ evolve 100000000 do
37
+ puts "clock: #{clock}"
38
+ #sleep 0.01
39
+ end
40
+ end
41
+ end
42
+
43
+ def help
44
+ puts <<-END
45
+ The current object is #{self.inspect}. Some commands:
46
+
47
+ q -- quit
48
+ sh! -- enter a system command shell
49
+ run N -- run quickly for N time steps (integer)
50
+ evolve T -- run quickly for T seconds (float)
51
+ tk -- turn on Tk window (-t on command line to start this way)
52
+ tk false -- turn off Tk window
53
+
54
+ Local vars persist between interrupts.
55
+ Continue slow execution by pressing Ctrl-D (maybe Ctrl-Z on windows).
56
+ Press Ctrl-C again to break into the shell. Use -s on command line
57
+ to start in shell.
58
+ END
59
+ end
60
+
61
+ def sh!
62
+ system ENV['SHELL'] || default_shell
63
+ end
64
+
65
+ def default_shell
66
+ puts "No SHELL environment variable, trying /bin/bash"
67
+ "/bin/bash"
68
+ end
69
+
70
+ def next_id
71
+ @next_id ||= 1
72
+ @next_id += 1
73
+ end
74
+
75
+ def create(*)
76
+ c = super
77
+ entered << c
78
+ c
79
+ end
80
+
81
+ def before_shell
82
+ @tkar.catch_up_within 0 if @tkar
83
+ puts "\nStopped #{self.inspect}"
84
+ end
85
+
86
+ def after_shell
87
+ @tkar.catch_up_within 0 if @tkar
88
+ puts "\nRunning #{self.inspect}"
89
+ end
90
+
91
+ def dragger id, x, y
92
+ c = find {|c| c.id == id}
93
+ c.x, c.y = x, y
94
+ end
95
+
96
+ def tk turn_on = true
97
+ require 'redshift/util/tkar-driver'
98
+ if turn_on
99
+ if not @tkar or @tkar.closed?
100
+ @tkar = TkarDriver.new(method :dragger) do |pipe|
101
+ pipe.puts <<-END
102
+ title Robot World
103
+ background gray95
104
+ height 600
105
+ width 600
106
+ view_at -50 -20
107
+ zoom_to 4
108
+
109
+ shape cone \ arc5,0,10,10,fc:yellow,oc:black,extent:30,start:165,style:pieslice \
110
+ text2,2,anchor:c,justify:center,width:100,text:*0,fc:blue
111
+
112
+ shape robot cone*0 \
113
+ arc5,5,2,2,fc:green,oc:green,extent:*1,start:0,style:pieslice \
114
+ arc5,-5,2,2,fc:red,oc:red,extent:*2,start:0,style:pieslice
115
+
116
+ shape circle oval*0,*0,*1,*1,oc:red
117
+ shape explosion oval*0,*0,*1,*1,oc:*2,fc:*2
118
+ shape missile \
119
+ arc2,0,4,4,fc:red,oc:black,extent:20,start:170,style:pieslice
120
+
121
+ END
122
+ ## the view_at seems to be needed to overcome a little
123
+ ## centering bug in tkar
124
+
125
+ each do |component|
126
+ pipe.puts component.tk_add if defined?(component.tk_add)
127
+ end
128
+ end
129
+
130
+ tk_update
131
+ end
132
+
133
+ elsif not turn_on and @tkar
134
+ @tkar.close
135
+ @tkar = nil
136
+ end
137
+ @tkar
138
+ end
139
+
140
+ def tk_update
141
+ if @tkar and
142
+ (entered.size > 0 or exited.size > 0 or (clock % 0.1).abs < 0.01)
143
+ @tkar.update do |pipe|
144
+ entered.each do |component|
145
+ pipe.puts component.tk_add if defined?(component.tk_add)
146
+ end
147
+
148
+ each do |component|
149
+ pipe.puts component.tk_update if defined?(component.tk_update)
150
+ end
151
+
152
+ exited.each do |component|
153
+ pipe.puts component.tk_delete if defined?(component.tk_delete)
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ def run(*)
160
+ super do
161
+ tk_update
162
+ entered.clear
163
+ exited.clear
164
+ yield self if block_given?
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,16 @@
1
+ # computes true distance and bearing angle to a single target,
2
+ # but won't scale up very well
3
+ class Tracker < RobotComponent
4
+ link :host => Robot
5
+ link :target => Robot
6
+
7
+ flow do
8
+ alg " distance =
9
+ sqrt(
10
+ pow(host.x - target.x, 2) +
11
+ pow(host.y - target.y, 2) ) "
12
+ alg " angle =
13
+ atan2(target.y - host.y,
14
+ target.x - host.x) "
15
+ end
16
+ end
@@ -0,0 +1,53 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+ require 'base'
3
+
4
+ world = RobotWorld.new
5
+ world.time_step = 0.01
6
+
7
+ r1 = world.create Robot do |r|
8
+ r.name = "robot 1"
9
+ r.x = 0
10
+ r.y = 0
11
+ end
12
+
13
+ r2 = world.create Robot do |r|
14
+ r.name = "robot 2"
15
+ r.x = -50
16
+ r.y = 0
17
+ r.heading = 0.1 * Math::PI
18
+ r.v = 10
19
+ end
20
+
21
+ r3 = world.create Robot do |r|
22
+ r.name = "robot 3"
23
+ r.x = 70
24
+ r.y = 10
25
+ r.heading = -0.9 * Math::PI
26
+ r.v = 5
27
+ end
28
+
29
+ 30.times do |i|
30
+ world.create Missile do |m|
31
+ m.x = -40
32
+ m.y = 40 + i*2
33
+ m.v = 20 - (i%10)
34
+ m.target = r2
35
+ end
36
+ end
37
+
38
+ 20.times do |i|
39
+ world.create Missile do |m|
40
+ m.x = -30
41
+ m.y = 40 + i*2
42
+ m.v = 20 - (i%10)
43
+ m.heading = i / 20
44
+ m.target = r3
45
+ end
46
+ end
47
+
48
+ robots = world.grep(Robot)
49
+ robots.each do |r|
50
+ r.radar.track_robots robots - [r]
51
+ end
52
+
53
+ world.main_loop_with_shell_and_tk(ARGV)
data/examples/shell.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # Shows how to use a customized IRB shell to handle Ctrl-C interrupts
2
2
 
3
3
  require 'redshift'
4
- require 'redshift/mixins/irb-shell'
5
4
  include RedShift
6
5
 
7
6
  require 'redshift/util/plot'
@@ -9,7 +8,7 @@ include Plot::PlotUtils
9
8
 
10
9
  # Adds an interactive ruby shell with plotting and animation commands.
11
10
  module ShellWorld
12
- include RedShift::Shellable
11
+ include RedShift::World::Shell
13
12
 
14
13
  def help
15
14
  puts <<-END
@@ -0,0 +1,102 @@
1
+ #include "buffer.h"
2
+
3
+ void rs_buffer_init(RSBuffer *buf, long len, double fill)
4
+ {
5
+ int i;
6
+ buf->ptr = ALLOC_N(double, len);
7
+ buf->len = len;
8
+ buf->offset = 0;
9
+ for (i=0; i<len; i++) {
10
+ buf->ptr[i] = fill;
11
+ }
12
+ }
13
+
14
+ void rs_buffer_resize(RSBuffer *buf, long len)
15
+ {
16
+ long i;
17
+ long old_len = buf->len;
18
+ long offset = buf->offset;
19
+ double *ptr = buf->ptr;
20
+ double *dst, *src;
21
+ double fill;
22
+
23
+ if (len < old_len) {
24
+ if (offset < len) {
25
+ dst = ptr + offset;
26
+ src = ptr + offset + old_len - len;
27
+ memmove(dst, src, (len - offset) * sizeof(double));
28
+ }
29
+ else {
30
+ dst = ptr;
31
+ src = ptr + offset - len;
32
+ offset = 0;
33
+ memmove(dst, src, len * sizeof(double));
34
+ }
35
+ REALLOC_N(ptr, double, len);
36
+ // ## maybe better: don't release space, just use less of it
37
+ }
38
+ else if (len > old_len) {
39
+ REALLOC_N(ptr, double, len);
40
+
41
+ fill = ptr[offset];
42
+ dst = ptr + offset + len - old_len;
43
+ src = ptr + offset;
44
+ memmove(dst, src, (old_len - offset) * sizeof(double));
45
+
46
+ for (i = 0; i < len - old_len; i++) {
47
+ ptr[offset + i] = fill;
48
+ }
49
+ }
50
+ else
51
+ return;
52
+
53
+ buf->len = len;
54
+ buf->offset = offset;
55
+ buf->ptr = ptr;
56
+ }
57
+
58
+ void rs_buffer_inhale_array(RSBuffer *buf, VALUE ary)
59
+ {
60
+ int size, i;
61
+
62
+ Check_Type(ary, T_ARRAY);
63
+
64
+ size = RARRAY_LEN(ary);
65
+ if (buf->ptr) {
66
+ REALLOC_N(buf->ptr, double, size);
67
+ }
68
+ else {
69
+ buf->ptr = ALLOC_N(double, size);
70
+ }
71
+ buf->len = size;
72
+ buf->offset = 0;
73
+
74
+ for (i = 0; i < size; i++) {
75
+ buf->ptr[i] = NUM2DBL(RARRAY_PTR(ary)[i]);
76
+ }
77
+ }
78
+
79
+ VALUE rs_buffer_exhale_array(RSBuffer *buf)
80
+ {
81
+ VALUE ary;
82
+ int i;
83
+ int j;
84
+ int size;
85
+
86
+ size = buf->len;
87
+ ary = rb_ary_new2(size);
88
+ RARRAY_LEN(ary) = size;
89
+ for (i = buf->offset, j=0; i < size; i++, j++) {
90
+ RARRAY_PTR(ary)[j] = rb_float_new(buf->ptr[i]);
91
+ }
92
+ for (i = 0; i < buf->offset; i++, j++) {
93
+ RARRAY_PTR(ary)[j] = rb_float_new(buf->ptr[i]);
94
+ }
95
+
96
+ return ary;
97
+ }
98
+
99
+ void
100
+ Init_buffer()
101
+ {
102
+ }
@@ -0,0 +1,17 @@
1
+ #ifndef buffer_h
2
+ #define buffer_h
3
+
4
+ #include <ruby.h>
5
+
6
+ typedef struct {
7
+ long len;
8
+ long offset;
9
+ double *ptr;
10
+ } RSBuffer;
11
+
12
+ void rs_buffer_init(RSBuffer *buf, long len, double fill);
13
+ void rs_buffer_resize(RSBuffer *buf, long len);
14
+ void rs_buffer_inhale_array(RSBuffer *buf, VALUE ary);
15
+ VALUE rs_buffer_exhale_array(RSBuffer *buf);
16
+
17
+ #endif
@@ -0,0 +1 @@
1
+ REDSHIFT_BUFFER_DIR = File.dirname(File.expand_path(__FILE__))
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'buffer'
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'isaac'
@@ -0,0 +1,129 @@
1
+ #include "ruby.h"
2
+ #include "rand.h"
3
+
4
+ #ifndef min
5
+ # define min(a,b) (((a)<(b)) ? (a) : (b))
6
+ #endif /* min */
7
+
8
+ static VALUE
9
+ ISAAC_s_allocate(VALUE klass)
10
+ {
11
+ randctx *ctx;
12
+
13
+ return Data_Make_Struct(klass, randctx, NULL, NULL, ctx);
14
+ }
15
+
16
+ /*
17
+ * Seed the generator with an array of up to ISAAC::RANDSIZ integers in the
18
+ * range 0..2**32-1. More entries are ignored. Missing entries are treated
19
+ * as 0. Returns +nil+.
20
+ */
21
+ static VALUE
22
+ ISAAC_srand(VALUE self, VALUE ary)
23
+ {
24
+ int i;
25
+ randctx *ctx;
26
+
27
+ Check_Type(ary, T_ARRAY);
28
+
29
+ Data_Get_Struct(self, randctx, ctx);
30
+
31
+ MEMZERO(ctx, randctx, 1);
32
+ for (i=min(RANDSIZ, RARRAY_LEN(ary))-1; i>=0; i--) {
33
+ ctx->randrsl[i] = NUM2UINT(RARRAY_PTR(ary)[i]);
34
+ }
35
+ rs_isaac_init(ctx, 1);
36
+
37
+ return Qnil;
38
+ }
39
+
40
+ /*
41
+ * Return a random integer in the range 0..2**32-1.
42
+ */
43
+ static VALUE
44
+ ISAAC_rand32(VALUE self)
45
+ {
46
+ randctx *ctx;
47
+
48
+ Data_Get_Struct(self, randctx, ctx);
49
+
50
+ if (!ctx->randcnt--) {
51
+ rs_isaac_rand(ctx);
52
+ ctx->randcnt=RANDSIZ-1;
53
+ }
54
+
55
+ return UINT2NUM(ctx->randrsl[ctx->randcnt]);
56
+ }
57
+
58
+ /*
59
+ * Return a random float in the range 0..1.
60
+ */
61
+ static VALUE
62
+ ISAAC_rand(VALUE self)
63
+ {
64
+ randctx *ctx;
65
+
66
+ Data_Get_Struct(self, randctx, ctx);
67
+
68
+ if (!ctx->randcnt--) {
69
+ rs_isaac_rand(ctx);
70
+ ctx->randcnt=RANDSIZ-1;
71
+ }
72
+
73
+ return rb_float_new(ctx->randrsl[ctx->randcnt] / 4294967295.0);
74
+ }
75
+
76
+ /* :nodoc: */
77
+ static VALUE
78
+ ISAAC_marshal_dump(VALUE self)
79
+ {
80
+ randctx *ctx;
81
+ int i;
82
+ int ary_size = sizeof(randctx)/sizeof(ub4);
83
+ VALUE ary;
84
+
85
+ Data_Get_Struct(self, randctx, ctx);
86
+
87
+ ary = rb_ary_new2(ary_size);
88
+ for (i = 0; i < ary_size; i++) {
89
+ rb_ary_push(ary, UINT2NUM(((ub4 *)ctx)[i]));
90
+ }
91
+
92
+ return ary;
93
+ }
94
+
95
+ /* :nodoc: */
96
+ static VALUE
97
+ ISAAC_marshal_load(VALUE self, VALUE ary)
98
+ {
99
+ randctx *ctx;
100
+ int i;
101
+ int ary_size = sizeof(randctx)/sizeof(ub4);
102
+
103
+ Data_Get_Struct(self, randctx, ctx);
104
+
105
+ if (RARRAY_LEN(ary) != ary_size)
106
+ rb_raise(rb_eArgError, "bad length in loaded ISAAC data");
107
+
108
+ for (i = 0; i < ary_size; i++) {
109
+ ((ub4 *)ctx)[i] = NUM2UINT(RARRAY_PTR(ary)[i]);
110
+ }
111
+
112
+ return self;
113
+ }
114
+
115
+ void
116
+ Init_isaac()
117
+ {
118
+ VALUE ISAAC;
119
+
120
+ ISAAC = rb_define_class("ISAAC", rb_cObject);
121
+ rb_define_alloc_func(ISAAC, ISAAC_s_allocate);
122
+ rb_define_method(ISAAC, "srand", ISAAC_srand, 1);
123
+ rb_define_method(ISAAC, "rand32", ISAAC_rand32, 0);
124
+ rb_define_method(ISAAC, "rand", ISAAC_rand, 0);
125
+ rb_define_method(ISAAC, "marshal_dump", ISAAC_marshal_dump, 0);
126
+ rb_define_method(ISAAC, "marshal_load", ISAAC_marshal_load, 1);
127
+
128
+ rb_const_set(ISAAC, rb_intern("RANDSIZ"), UINT2NUM(RANDSIZ));
129
+ }