redshift 1.3.17 → 1.3.18

Sign up to get free protection for your applications and to get access to all the features.
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
+ }