penguin_queue 0.1.2 → 0.1.3

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.
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
  - - ">="