penguin_queue 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9d70fcdcdbb5aebbebec83821a6127e80fc6f583
4
- data.tar.gz: 0efca553d509e7a8951f9c3cd44315dff21d632b
3
+ metadata.gz: bb2b3114b3a347a0a1f30b0bd72180595e385f4e
4
+ data.tar.gz: bad8b670607f5eec92c26795de6b0f2217571c5e
5
5
  SHA512:
6
- metadata.gz: bceb560f69ff8e4f61afcc0a227ad7d43c10b960c0d4a1c487c3e874eb51a9950573521ef4c5159f55d6ab87ad38d8f7d0a9d80ea8e003cab4be93c4542b873a
7
- data.tar.gz: 4fa133b95cf698d674ba7ae9eb5831500a213f2f78a0781237f6d9345dc5a67bc50b742818b91639488d4496656457292ce57842f0b8bcf43eaab4735e67b3b6
6
+ metadata.gz: 7ae75f4e9505ebe8a27ed745899a493768d46ef51e863f4beb1ce90afb0cbc1145983a05d87c37814cfab2459178fb57c929432d50d438f83afb3fd942ddd1bc
7
+ data.tar.gz: 8636a9b92b784fae27a3e5870e805ceec105035a533382b0f6c4ad22627b0c621653839f47d90f324dd7a32f0efa120dbab661ae824559b5a846371a3992a6bf
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.0
5
+ - 2.3.0
6
+ - 2.4.0
7
+ before_install: gem install bundler -v 1.13.7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- penguin_queue (0.1.2)
4
+ penguin_queue (0.1.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,4 +1,9 @@
1
- # Priority Queue
1
+ # Penguin Queue
2
+
3
+ [![Build Status](https://travis-ci.org/tompng/penguin_queue.svg?branch=master)](https://travis-ci.org/tompng/penguin_queue)
4
+
5
+ Ruby priority-queue library
6
+
2
7
  ```ruby
3
8
  10000.times { array << rand; array.delete(array.min) } #=> slow when array.size is large
4
9
  10000.times { pq << rand; pq.deq } #=> fast even if pq.size is large
@@ -38,7 +43,7 @@ pq.size.times.map { pq.deq } #=> [8, 6, 4, 2, 0]
38
43
  ```ruby
39
44
  # initialize
40
45
  PenguinQueue.new
41
- PenguinQueue.new(order) # min(default) or max
46
+ PenguinQueue.new(order) # :min(default) or :max
42
47
  PenguinQueue.new(&calc_priority_from_element_proc)
43
48
  # enqueue
44
49
  <<(e) enq(e) push(e) unshift(e)
@@ -1,12 +1,24 @@
1
1
  #include <ruby.h>
2
2
 
3
- static ID id_priority, id_cmp, id_call, id_order, id_max, id_min;
3
+ static ID id_priority, id_cmp, id_call, id_max, id_min;
4
4
  #define RB_STR_BUF_CAT(rstr, cstr) rb_str_buf_cat((rstr), (cstr), sizeof(cstr)-1);
5
5
  struct node {
6
6
  long index, id;
7
7
  VALUE queue, priority, value;
8
8
  };
9
- VALUE node_class;
9
+ struct queue_data{
10
+ long counter;
11
+ int compare_sgn;
12
+ VALUE heap, compare_by;
13
+ };
14
+ #define NODE_DECLARE_PTR(name) struct node *name;
15
+ #define NODE_GET_PTR(self, name) Data_Get_Struct(self, struct node, name);
16
+ #define QUEUE_DECLARE_PTR(name) struct queue_data *name;
17
+ #define QUEUE_GET_PTR(self, name) Data_Get_Struct(self, struct queue_data, name);
18
+ #define NODE_PREPARE(self, name) NODE_DECLARE_PTR(name);NODE_GET_PTR(self, name);
19
+ #define QUEUE_PREPARE(self, name) QUEUE_DECLARE_PTR(name);QUEUE_GET_PTR(self, name);
20
+
21
+ VALUE queue_class, node_class;
10
22
  void node_mark(struct node *ptr){
11
23
  rb_gc_mark(ptr->queue);
12
24
  rb_gc_mark(ptr->priority);
@@ -21,7 +33,6 @@ VALUE node_alloc_internal(long index, long id, VALUE queue, VALUE priority, VALU
21
33
  ptr->value = value;
22
34
  return Data_Wrap_Struct(node_class, node_mark, RUBY_DEFAULT_FREE, ptr);
23
35
  }
24
- #define NODE_PREPARE(self, name) struct node *name;Data_Get_Struct(self, struct node, name);
25
36
  VALUE node_pri(VALUE self){
26
37
  NODE_PREPARE(self, ptr);
27
38
  return ptr->priority;
@@ -31,8 +42,8 @@ VALUE node_val(VALUE self){
31
42
  return ptr->value;
32
43
  }
33
44
  VALUE node_inspect(VALUE self){
34
- NODE_PREPARE(self, nptr);
35
45
  VALUE str = rb_str_buf_new(0);
46
+ NODE_PREPARE(self, nptr);
36
47
  rb_str_buf_append(str, rb_class_name(CLASS_OF(self)));
37
48
  RB_STR_BUF_CAT(str, "{priority: ");
38
49
  rb_str_buf_append(str, rb_inspect(nptr->priority));
@@ -42,13 +53,8 @@ VALUE node_inspect(VALUE self){
42
53
  return str;
43
54
  }
44
55
 
45
- struct queue_data{
46
- long counter;
47
- int compare_sgn;
48
- VALUE heap, compare_by;
49
- };
50
-
51
56
  long compare(VALUE a, VALUE b){
57
+ #ifdef RB_FIXNUM_P
52
58
  if(RB_FIXNUM_P(a)&&RB_FIXNUM_P(b))
53
59
  return (long)a > (long)b ? 1 : (long)a < (long)b ? -1 : 0;
54
60
  if(RB_FLOAT_TYPE_P(a)&&RB_FLOAT_TYPE_P(b)){
@@ -57,14 +63,14 @@ long compare(VALUE a, VALUE b){
57
63
  }
58
64
  if(RB_TYPE_P(a, T_STRING)&&RB_TYPE_P(b, T_STRING))
59
65
  return rb_str_cmp(a, b);
60
- VALUE cmp = rb_funcall(a, id_cmp, 1, b);
61
- if(NIL_P(cmp))rb_cmperr(a,b);
62
- return rb_fix2long(cmp);
66
+ return rb_fix2long(rb_funcall(a, id_cmp, 1, b));
67
+ #else
68
+ return FIX2LONG(rb_funcall(a, id_cmp, 1, b));
69
+ #endif
63
70
  }
64
71
 
65
72
  long compare_id(long a, long b){return a>b?1:a<b?-1:0;}
66
73
 
67
- #define QUEUE_PREPARE(self, name) struct queue_data *name;Data_Get_Struct(self, struct queue_data, name);
68
74
  #define OPTHASH_GIVEN_P(opts) (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
69
75
 
70
76
  void queue_mark(struct queue_data *self){
@@ -87,8 +93,8 @@ VALUE queue_alloc(VALUE klass){
87
93
  }
88
94
 
89
95
  VALUE queue_initialize(int argc, VALUE *argv, VALUE self){
96
+ VALUE order;
90
97
  QUEUE_PREPARE(self, ptr);
91
- VALUE opts, order;
92
98
  if(argc == 0)return self;
93
99
  rb_scan_args(argc, argv, "1", &order);
94
100
  if(order == ID2SYM(id_max)){
@@ -108,16 +114,19 @@ VALUE queue_clear(VALUE self){
108
114
  }
109
115
 
110
116
  void queue_up(VALUE self, VALUE node){
117
+ int sgn;
111
118
  QUEUE_PREPARE(self, ptr);
112
- int sgn = ptr->compare_sgn;
119
+ sgn = ptr->compare_sgn;
113
120
  RARRAY_PTR_USE(ptr->heap, heap, {
121
+ long index;
114
122
  NODE_PREPARE(node, nptr);
115
- long index = nptr->index;
123
+ index = nptr->index;
116
124
  while(index > 1){
125
+ long cmp;
117
126
  long pindex = index/2;
118
127
  VALUE pnode = heap[pindex];
119
128
  NODE_PREPARE(pnode, pptr);
120
- long cmp = compare(pptr->priority, nptr->priority)*sgn;
129
+ cmp = compare(pptr->priority, nptr->priority)*sgn;
121
130
  if(!cmp)cmp=compare_id(pptr->id, nptr->id);
122
131
  if(cmp<0)break;
123
132
  pptr->index = index;
@@ -130,20 +139,24 @@ void queue_up(VALUE self, VALUE node){
130
139
  }
131
140
 
132
141
  void queue_down(VALUE self, VALUE node){
142
+ int sgn;
143
+ long length;
133
144
  QUEUE_PREPARE(self, ptr);
134
- int sgn = ptr->compare_sgn;
135
- long length = RARRAY_LEN(ptr->heap);
145
+ sgn = ptr->compare_sgn;
146
+ length = RARRAY_LEN(ptr->heap);
136
147
  RARRAY_PTR_USE(ptr->heap, heap, {
148
+ long index;
137
149
  NODE_PREPARE(node, nptr);
138
- long index = nptr->index;
150
+ index = nptr->index;
139
151
  while(2*index < length){
140
152
  long lindex = 2*index;
141
153
  VALUE lnode = heap[lindex];
142
154
  NODE_PREPARE(lnode, lptr);
143
155
  if(lindex+1 < length){
156
+ long cmp;
144
157
  VALUE rnode = heap[lindex+1];
145
158
  NODE_PREPARE(rnode, rptr);
146
- long cmp = compare(lptr->priority, rptr->priority)*sgn;
159
+ cmp = compare(lptr->priority, rptr->priority)*sgn;
147
160
  if(!cmp)cmp=compare_id(lptr->id, rptr->id);
148
161
  if(cmp >= 0){
149
162
  lindex += 1;
@@ -164,19 +177,24 @@ void queue_down(VALUE self, VALUE node){
164
177
  }
165
178
 
166
179
  VALUE queue_remove_node(VALUE self, VALUE node){
180
+ int sgn;
181
+ long length;
182
+ QUEUE_DECLARE_PTR(ptr);
183
+ NODE_DECLARE_PTR(nptr);
167
184
  if(!rb_obj_is_kind_of(node, node_class))return Qnil;
168
- QUEUE_PREPARE(self, ptr);
169
- NODE_PREPARE(node, nptr);
170
- int sgn = ptr->compare_sgn;
171
- long length = RARRAY_LEN(ptr->heap);
185
+ QUEUE_GET_PTR(self, ptr);
186
+ NODE_GET_PTR(node, nptr);
187
+ sgn = ptr->compare_sgn;
188
+ length = RARRAY_LEN(ptr->heap);
172
189
  if(nptr->index >= length || RARRAY_AREF(ptr->heap, nptr->index) != node)return Qnil;
173
190
  RARRAY_PTR_USE(ptr->heap, heap, {
191
+ long cmp;
174
192
  VALUE replace_node = rb_ary_pop(ptr->heap);
175
- if(replace_node == node)return Qnil;
176
193
  NODE_PREPARE(replace_node, rptr);
194
+ if(replace_node == node)return Qnil;
177
195
  heap[nptr->index] = replace_node;
178
196
  rptr->index = nptr->index;
179
- long cmp = compare(rptr->priority, nptr->priority)*sgn;
197
+ cmp = compare(rptr->priority, nptr->priority)*sgn;
180
198
  if(!cmp)cmp = compare_id(rptr->id, nptr->id);
181
199
  if(cmp > 0){
182
200
  queue_down(nptr->queue, replace_node);
@@ -194,12 +212,17 @@ VALUE node_remove(VALUE self){
194
212
  }
195
213
 
196
214
  void node_update_priority_internal(VALUE node, VALUE priority){
197
- NODE_PREPARE(node, nptr);
198
- QUEUE_PREPARE(nptr->queue, ptr);
199
- int sgn = ptr->compare_sgn;
200
- VALUE priority_was = nptr->priority;
215
+ int sgn;
216
+ long cmp;
217
+ VALUE priority_was;
218
+ NODE_DECLARE_PTR(nptr);
219
+ QUEUE_DECLARE_PTR(ptr);
220
+ NODE_GET_PTR(node, nptr);
221
+ QUEUE_GET_PTR(nptr->queue, ptr);
222
+ sgn = ptr->compare_sgn;
223
+ priority_was = nptr->priority;
201
224
  nptr->priority = priority;
202
- long cmp = compare(priority, priority_was)*sgn;
225
+ cmp = compare(priority, priority_was)*sgn;
203
226
  if(cmp == 0)return;
204
227
  RARRAY_PTR_USE(ptr->heap, heap, {
205
228
  if(heap[nptr->index] != node)return;
@@ -212,16 +235,20 @@ void node_update_priority_internal(VALUE node, VALUE priority){
212
235
  }
213
236
 
214
237
  VALUE node_update_priority(VALUE node, VALUE priority){
215
- NODE_PREPARE(node, nptr);
216
- QUEUE_PREPARE(nptr->queue, ptr);
238
+ NODE_DECLARE_PTR(nptr);
239
+ QUEUE_DECLARE_PTR(ptr);
240
+ NODE_GET_PTR(node, nptr);
241
+ QUEUE_GET_PTR(nptr->queue, ptr);
217
242
  if(ptr->compare_by != Qnil)rb_raise(rb_eRuntimeError, "priority update not supported on queue initialized with block");
218
243
  node_update_priority_internal(node, priority);
219
244
  return priority;
220
245
  }
221
246
 
222
247
  VALUE node_update_value(VALUE node, VALUE value){
223
- NODE_PREPARE(node, nptr);
224
- QUEUE_PREPARE(nptr->queue, ptr);
248
+ NODE_DECLARE_PTR(nptr);
249
+ QUEUE_DECLARE_PTR(ptr);
250
+ NODE_GET_PTR(node, nptr);
251
+ QUEUE_GET_PTR(nptr->queue, ptr);
225
252
  nptr->value = value;
226
253
  if(ptr->compare_by != Qnil){
227
254
  VALUE priority = rb_funcall(ptr->compare_by, id_call, 1, value);
@@ -231,12 +258,14 @@ VALUE node_update_value(VALUE node, VALUE value){
231
258
  }
232
259
 
233
260
  VALUE queue_enq_vp(VALUE self, VALUE value, VALUE priority){
261
+ long length;
262
+ VALUE node;
234
263
  QUEUE_PREPARE(self, ptr);
235
264
  if(ptr->compare_by != Qnil){
236
265
  priority = rb_funcall(ptr->compare_by, id_call, 1, value);
237
266
  }
238
- long length = RARRAY_LEN(ptr->heap);
239
- VALUE node = node_alloc_internal(length, ptr->counter, self, priority, value);
267
+ length = RARRAY_LEN(ptr->heap);
268
+ node = node_alloc_internal(length, ptr->counter, self, priority, value);
240
269
  ptr->counter++;
241
270
  rb_ary_push(ptr->heap, node);
242
271
  queue_up(self, node);
@@ -258,8 +287,9 @@ VALUE queue_push(VALUE self, VALUE value){
258
287
  }
259
288
 
260
289
  VALUE queue_first_node(VALUE self){
290
+ long length;
261
291
  QUEUE_PREPARE(self, ptr);
262
- long length = RARRAY_LEN(ptr->heap);
292
+ length = RARRAY_LEN(ptr->heap);
263
293
  if(length == 1)return Qnil;
264
294
  RARRAY_PTR_USE(ptr->heap, heap, {
265
295
  return heap[1];
@@ -267,20 +297,23 @@ VALUE queue_first_node(VALUE self){
267
297
  }
268
298
  VALUE queue_first(VALUE self){
269
299
  VALUE node = queue_first_node(self);
300
+ NODE_DECLARE_PTR(nptr);
270
301
  if(node == Qnil)return Qnil;
271
- NODE_PREPARE(node, nptr);
302
+ NODE_GET_PTR(node, nptr);
272
303
  return nptr->value;
273
304
  }
274
305
  VALUE queue_first_with_priority(VALUE self){
275
306
  VALUE node = queue_first_node(self);
307
+ NODE_DECLARE_PTR(nptr);
276
308
  if(node == Qnil)return Qnil;
277
- NODE_PREPARE(node, nptr);
309
+ NODE_GET_PTR(node, nptr);
278
310
  return rb_ary_new_from_args(2, nptr->value, nptr->priority);
279
311
  }
280
312
 
281
313
  VALUE queue_deq_node(VALUE self){
314
+ long length;
282
315
  QUEUE_PREPARE(self, ptr);
283
- long length = RARRAY_LEN(ptr->heap);
316
+ length = RARRAY_LEN(ptr->heap);
284
317
  if(length == 1)return Qnil;
285
318
  RARRAY_PTR_USE(ptr->heap, heap, {
286
319
  VALUE first = heap[1];
@@ -296,19 +329,23 @@ VALUE queue_deq_node(VALUE self){
296
329
  VALUE queue_deq(int argc, VALUE *argv, VALUE self){
297
330
  if(argc == 0){
298
331
  VALUE node = queue_deq_node(self);
332
+ NODE_DECLARE_PTR(nptr);
299
333
  if(node == Qnil)return Qnil;
300
- NODE_PREPARE(node, nptr);
334
+ NODE_GET_PTR(node, nptr);
301
335
  return nptr->value;
302
336
  }else{
303
- VALUE nv;
337
+ VALUE nv, result;
338
+ int i;
339
+ long n, length;
340
+ QUEUE_DECLARE_PTR(ptr);
304
341
  rb_scan_args(argc, argv, "1", &nv);
305
- long n = NUM2LONG(nv);
342
+ n = NUM2LONG(nv);
306
343
  if(n<0)rb_raise(rb_eArgError, "negative array size");
307
- QUEUE_PREPARE(self, ptr);
308
- long length = RARRAY_LEN(ptr->heap)-1;
344
+ QUEUE_GET_PTR(self, ptr);
345
+ length = RARRAY_LEN(ptr->heap)-1;
309
346
  if(n>length)n=length;
310
- VALUE result = rb_ary_new_capa(n);
311
- for(int i=0;i<n;i++){
347
+ result = rb_ary_new_capa(n);
348
+ for(i=0;i<n;i++){
312
349
  VALUE node = queue_deq_node(self);
313
350
  NODE_PREPARE(node, nptr);
314
351
  rb_ary_push(result, nptr->value);
@@ -318,8 +355,9 @@ VALUE queue_deq(int argc, VALUE *argv, VALUE self){
318
355
  }
319
356
  VALUE queue_deq_with_priority(VALUE self){
320
357
  VALUE node = queue_deq_node(self);
358
+ NODE_DECLARE_PTR(nptr);
321
359
  if(node == Qnil)return Qnil;
322
- NODE_PREPARE(node, nptr);
360
+ NODE_GET_PTR(node, nptr);
323
361
  return rb_ary_new_from_args(2, nptr->value, nptr->priority);
324
362
  }
325
363
 
@@ -341,8 +379,8 @@ VALUE queue_is_max(VALUE self){
341
379
  return QUEUE_PTR_IS_MIN(ptr) ? Qfalse : Qtrue;
342
380
  }
343
381
  VALUE queue_inspect(VALUE self){
344
- QUEUE_PREPARE(self, ptr);
345
382
  VALUE str = rb_str_buf_new(0);
383
+ QUEUE_PREPARE(self, ptr);
346
384
  rb_str_buf_append(str, rb_class_name(CLASS_OF(self)));
347
385
  RB_STR_BUF_CAT(str, "{order: ");
348
386
  if(QUEUE_PTR_IS_MIN(ptr)){
@@ -363,7 +401,7 @@ void Init_penguin_queue(void){
363
401
  id_max = rb_intern("max");
364
402
  id_min = rb_intern("min");
365
403
 
366
- VALUE queue_class = rb_define_class("PenguinQueue", rb_cObject);
404
+ queue_class = rb_define_class("PenguinQueue", rb_cObject);
367
405
  rb_define_alloc_func(queue_class, queue_alloc);
368
406
  rb_define_method(queue_class, "initialize", queue_initialize, -1);
369
407
  rb_define_method(queue_class, "size", queue_size, 0);
@@ -1,3 +1,3 @@
1
1
  class PenguinQueue
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -13,6 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.description = %q{C Ext Priority Queue (binary heap)}
14
14
  spec.homepage = "https://github.com/tompng/penguin_queue"
15
15
  spec.license = "MIT"
16
+ spec.required_ruby_version = '>= 2.2.0'
16
17
  spec.extensions = %w[ext/penguin_queue/extconf.rb]
17
18
 
18
19
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: penguin_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - tompng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-20 00:00:00.000000000 Z
11
+ date: 2017-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -75,6 +75,7 @@ extensions:
75
75
  extra_rdoc_files: []
76
76
  files:
77
77
  - ".gitignore"
78
+ - ".travis.yml"
78
79
  - Gemfile
79
80
  - Gemfile.lock
80
81
  - LICENSE.txt
@@ -99,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
100
  requirements:
100
101
  - - ">="
101
102
  - !ruby/object:Gem::Version
102
- version: '0'
103
+ version: 2.2.0
103
104
  required_rubygems_version: !ruby/object:Gem::Requirement
104
105
  requirements:
105
106
  - - ">="