roaring 0.3.0 → 0.4.1

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
  SHA256:
3
- metadata.gz: 0e21e62ddcac0d57cf83948329add1ead73e1299adc691b57dd940e7e5ca5306
4
- data.tar.gz: 1367042b6b8d27c24f9e124cf8c081bc18aa153e4431cb6339181c65904dbb68
3
+ metadata.gz: 3f2956df800830dc45bb3b8e63fd1b7795c39a73ab52f5671e651ca1087e1572
4
+ data.tar.gz: 74b06f13df663851dd703b2888cd3b465fe788a794dcb0cadca5d1b534db023e
5
5
  SHA512:
6
- metadata.gz: 3b94ccd487a8b5e28b6130e25a759f4ab1d226670cb30063cede4c5815a19c69481a5a5f7bbfafc6ebbca6e55fdf6e85166e63f0c5fe13a82bfeaba3d107ec7d
7
- data.tar.gz: 9735a5df2fff46c07e917fc4cbd421fbff2bcca9304cf0da3f70c9f9e0ea12ed54447280b7a17b18f9d5a43a0f178f2d6fd840d5017dc80494b1f7add81ee242
6
+ metadata.gz: 18a68702d1d236e6817c542dcbb15d32515f76263b0e5f074837bdde8a5bc9ca5ff88976eba18d67b1cd041307b22a81a72e79f6d7b25124b80b2f14028e9ba0
7
+ data.tar.gz: 44ca8c98572f932a23d7488afd87bc05d3c0618062d912bc71b9f319497ba5ac3e824e046011b192198b8c90686ebeda972f1e15104428684cdb2dcc2761dd3d
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --embed-mixins --no-private
data/Gemfile CHANGED
@@ -11,3 +11,6 @@ gem "rake-compiler"
11
11
  gem "debug"
12
12
 
13
13
  gem "minitest", "~> 5.0"
14
+
15
+ gem "yard"
16
+ gem "benchmark-ips"
data/README.md CHANGED
@@ -1,9 +1,6 @@
1
1
  # Roaring
2
2
 
3
- A Ruby wrapper for CRoaring (a C/C++ implementation at https://github.com/RoaringBitmap/CRoaring)
4
-
5
- Roaring Bitmaps are a compressed bitmap/bitset format/library.
6
- More information and papers can be found at https://roaringbitmap.org/
3
+ [Roaring Bitmaps](http://www.roaringbitmap.org/about/) are a compressed bitmap/bitset format/library. Think of it like a `Set` which can only hold (32-bit or 64-bit) `Integer`s, with much lower memory use and supporting fast set operations.
7
4
 
8
5
  ## Installation
9
6
 
@@ -16,20 +13,26 @@ Install the gem and add to the application's Gemfile by executing:
16
13
  ``` ruby
17
14
  require "roaring"
18
15
 
19
- # Bitmaps can efficiently store a large range of 32-bit integers
20
- bitmap = Roaring::Bitmap[1, 2, 3, 999]
16
+ # Bitmap32 can efficiently store a large range of 32-bit integers
17
+ bitmap = Roaring::Bitmap32[1, 2, 3, 999]
21
18
  bitmap << (2**32 - 1)
22
19
 
20
+ # Bitmap64 can efficiently store a large range of 64-bit integers
21
+ bitmap = Roaring::Bitmap64[1, 2, 3, 999]
22
+ bitmap << (2**32 + 1)
23
+ bitmap << (2**64 - 1)
24
+
23
25
  # Element access
24
26
  bitmap.each { }
25
27
  bitmap.first # => 1
26
28
  bitmap.min # => 1
27
- bitmap.max # => 4294967295
28
- bitmap.last # => 4294967295
29
+ bitmap.max # => 18446744073709551615
30
+ bitmap.last # => 18446744073709551615
29
31
  bitmap[3] # => 999
32
+ bitmap.to_a # => [1, 2, 3, 999, 4294967297, 18446744073709551615]
30
33
 
31
- b1 = Roaring::Bitmap.new(200...500)
32
- b2 = Roaring::Bitmap.new(100...1000)
34
+ b1 = Roaring::Bitmap64.new(200...500)
35
+ b2 = Roaring::Bitmap64.new(100...1000)
33
36
 
34
37
  # Support common set operations
35
38
  (b1 & b2).size # => 300
@@ -41,12 +44,14 @@ b1 < b2 # => true
41
44
 
42
45
  # (De)Serialization (also available via Marshal#{dump,load})
43
46
  dump = bitmap.serialize
44
- loaded = Roaring::Bitmap.deserialize(dump)
47
+ loaded = Roaring::Bitmap64.deserialize(dump)
45
48
  loaded == bitmap # => true
46
49
  ```
47
50
 
48
51
  ## Development
49
52
 
53
+ This is a Ruby wrapper around [CRoaring](https://github.com/RoaringBitmap/CRoaring)
54
+
50
55
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
56
 
52
57
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
data/Rakefile CHANGED
@@ -3,6 +3,12 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "rake/testtask"
5
5
 
6
+ require "yard"
7
+
8
+ YARD::Rake::YardocTask.new do |t|
9
+ t.files = ["lib/**/*.rb", "ext/**/*.c"]
10
+ end
11
+
6
12
  Rake::TestTask.new(:test) do |t|
7
13
  t.libs << "test"
8
14
  t.libs << "lib"
@@ -17,14 +23,13 @@ Rake::ExtensionTask.new("roaring") do |ext|
17
23
  ext.lib_dir = "lib/roaring"
18
24
  end
19
25
 
26
+ desc "Update vendored CRoaring library"
20
27
  task :update_roaring do
21
- require "open-uri"
22
-
23
- ["roaring.c", "roaring.h"].each do |filename|
24
- url = "https://github.com/RoaringBitmap/CRoaring/releases/latest/download/#{filename}"
25
- source = URI.open(url).read
26
- File.write("#{__dir__}/ext/roaring/#{filename}", source)
27
- end
28
+ rm_rf "tmp/CRoaring"
29
+ sh "git clone --depth=1 https://github.com/RoaringBitmap/CRoaring tmp/CRoaring"
30
+ sh "cd tmp/CRoaring && sh amalgamation.sh"
31
+ cp "tmp/CRoaring/roaring.c", "ext/roaring/roaring.c"
32
+ cp "tmp/CRoaring/roaring.h", "ext/roaring/roaring.h"
28
33
  end
29
34
 
30
35
  task default: %i[compile test]
data/benchmark/to_a.rb ADDED
@@ -0,0 +1,15 @@
1
+ require "benchmark/ips"
2
+ require "roaring"
3
+
4
+ small_bitmap = Roaring::Bitmap32[1,2,3,4]
5
+ large_bitmap = Roaring::Bitmap32[1..1000]
6
+
7
+ Benchmark.ips do |x|
8
+ x.report "small_bitmap.to_a" do
9
+ small_bitmap.to_a
10
+ end
11
+
12
+ x.report "large_bitmap.to_a" do
13
+ large_bitmap.to_a
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require "benchmark/ips"
2
+ require "roaring"
3
+
4
+ small_bitmap = Roaring::Bitmap32[1,2,3,4]
5
+ large_bitmap = Roaring::Bitmap32[1..1000]
6
+
7
+ Benchmark.ips do |x|
8
+ x.report "small_bitmap.to_set" do
9
+ small_bitmap.to_set
10
+ end
11
+
12
+ x.report "large_bitmap.to_set" do
13
+ large_bitmap.to_set
14
+ end
15
+ end
@@ -48,6 +48,7 @@ static roaring_bitmap_t *get_bitmap(VALUE obj) {
48
48
  return bitmap;
49
49
  }
50
50
 
51
+ // Replaces the contents of `self` with another bitmap
51
52
  static VALUE rb_roaring32_replace(VALUE self, VALUE other) {
52
53
  roaring_bitmap_t *self_data = get_bitmap(self);
53
54
  roaring_bitmap_t *other_data = get_bitmap(other);
@@ -57,6 +58,7 @@ static VALUE rb_roaring32_replace(VALUE self, VALUE other) {
57
58
  return self;
58
59
  }
59
60
 
61
+ // @return [Integer] the number of elements in the bitmap
60
62
  static VALUE rb_roaring32_cardinality(VALUE self)
61
63
  {
62
64
  roaring_bitmap_t *data = get_bitmap(self);
@@ -64,6 +66,8 @@ static VALUE rb_roaring32_cardinality(VALUE self)
64
66
  return ULONG2NUM(cardinality);
65
67
  }
66
68
 
69
+ // Adds an element from the bitmap
70
+ // @param val [Integer] the value to add
67
71
  static VALUE rb_roaring32_add(VALUE self, VALUE val)
68
72
  {
69
73
  roaring_bitmap_t *data = get_bitmap(self);
@@ -73,6 +77,9 @@ static VALUE rb_roaring32_add(VALUE self, VALUE val)
73
77
  return self;
74
78
  }
75
79
 
80
+ // Adds an element from the bitmap
81
+ // @see {add}
82
+ // @return `self` if value was add, `nil` if value was already in the bitmap
76
83
  static VALUE rb_roaring32_add_p(VALUE self, VALUE val)
77
84
  {
78
85
  roaring_bitmap_t *data = get_bitmap(self);
@@ -81,6 +88,19 @@ static VALUE rb_roaring32_add_p(VALUE self, VALUE val)
81
88
  return roaring_bitmap_add_checked(data, num) ? self : Qnil;
82
89
  }
83
90
 
91
+ static VALUE rb_roaring32_add_range_closed(VALUE self, VALUE minv, VALUE maxv)
92
+ {
93
+ roaring_bitmap_t *data = get_bitmap(self);
94
+
95
+ uint32_t min = NUM2UINT32(minv);
96
+ uint32_t max = NUM2UINT32(maxv);
97
+
98
+ roaring_bitmap_add_range_closed(data, min, max);
99
+
100
+ return self;
101
+ }
102
+
103
+ // Removes an element from the bitmap
84
104
  static VALUE rb_roaring32_remove(VALUE self, VALUE val)
85
105
  {
86
106
  roaring_bitmap_t *data = get_bitmap(self);
@@ -90,6 +110,10 @@ static VALUE rb_roaring32_remove(VALUE self, VALUE val)
90
110
  return self;
91
111
  }
92
112
 
113
+ // Removes an element from the bitmap
114
+ //
115
+ // @see {remove}
116
+ // @return [self,nil] `self` if value was removed, `nil` if the value wasn't in the bitmap
93
117
  static VALUE rb_roaring32_remove_p(VALUE self, VALUE val)
94
118
  {
95
119
  roaring_bitmap_t *data = get_bitmap(self);
@@ -98,6 +122,7 @@ static VALUE rb_roaring32_remove_p(VALUE self, VALUE val)
98
122
  return roaring_bitmap_remove_checked(data, num) ? self : Qnil;
99
123
  }
100
124
 
125
+ // @return [Boolean] `true` if the bitmap is contains `val`, otherwise `false`
101
126
  static VALUE rb_roaring32_include_p(VALUE self, VALUE val)
102
127
  {
103
128
  roaring_bitmap_t *data = get_bitmap(self);
@@ -106,12 +131,14 @@ static VALUE rb_roaring32_include_p(VALUE self, VALUE val)
106
131
  return RBOOL(roaring_bitmap_contains(data, num));
107
132
  }
108
133
 
134
+ // @return [Boolean] `true` if the bitmap is empty, otherwise `false`
109
135
  static VALUE rb_roaring32_empty_p(VALUE self)
110
136
  {
111
137
  roaring_bitmap_t *data = get_bitmap(self);
112
138
  return RBOOL(roaring_bitmap_is_empty(data));
113
139
  }
114
140
 
141
+ // Removes all elements from the bitmap
115
142
  static VALUE rb_roaring32_clear(VALUE self)
116
143
  {
117
144
  roaring_bitmap_t *data = get_bitmap(self);
@@ -124,6 +151,8 @@ bool rb_roaring32_each_i(uint32_t value, void *param) {
124
151
  return true; // iterate till the end
125
152
  }
126
153
 
154
+ // Iterates over every element in the bitmap
155
+ // @return [self]
127
156
  static VALUE rb_roaring32_each(VALUE self)
128
157
  {
129
158
  roaring_bitmap_t *data = get_bitmap(self);
@@ -131,6 +160,8 @@ static VALUE rb_roaring32_each(VALUE self)
131
160
  return self;
132
161
  }
133
162
 
163
+ // Find the nth smallest integer in the bitmap
164
+ // @return [Integer,nil] The nth integer in the bitmap, or `nil` if `rankv` is `>= cardinality`
134
165
  static VALUE rb_roaring32_aref(VALUE self, VALUE rankv)
135
166
  {
136
167
  roaring_bitmap_t *data = get_bitmap(self);
@@ -146,6 +177,8 @@ static VALUE rb_roaring32_aref(VALUE self, VALUE rankv)
146
177
  return self;
147
178
  }
148
179
 
180
+ // Find the smallest integer in the bitmap
181
+ // @return [Integer,nil] The smallest integer in the bitmap, or `nil` if it is empty
149
182
  static VALUE rb_roaring32_min(VALUE self)
150
183
  {
151
184
  roaring_bitmap_t *data = get_bitmap(self);
@@ -158,6 +191,8 @@ static VALUE rb_roaring32_min(VALUE self)
158
191
  }
159
192
  }
160
193
 
194
+ // Find the largest integer in the bitmap
195
+ // @return [Integer,nil] The largest integer in the bitmap, or `nil` if it is empty
161
196
  static VALUE rb_roaring32_max(VALUE self)
162
197
  {
163
198
  roaring_bitmap_t *data = get_bitmap(self);
@@ -170,12 +205,16 @@ static VALUE rb_roaring32_max(VALUE self)
170
205
  }
171
206
  }
172
207
 
208
+ // Attemps to internally optimize the representation of bitmap by finding runs, consecutive sequences of integers.
209
+ // @return [Boolean] whether the result has at least one run container
173
210
  static VALUE rb_roaring32_run_optimize(VALUE self)
174
211
  {
175
212
  roaring_bitmap_t *data = get_bitmap(self);
176
213
  return RBOOL(roaring_bitmap_run_optimize(data));
177
214
  }
178
215
 
216
+ // Serializes a bitmap into a string
217
+ // @return [string]
179
218
  static VALUE rb_roaring32_serialize(VALUE self)
180
219
  {
181
220
  roaring_bitmap_t *data = get_bitmap(self);
@@ -189,13 +228,58 @@ static VALUE rb_roaring32_serialize(VALUE self)
189
228
  return str;
190
229
  }
191
230
 
231
+ // Loads a previously serialized bitmap
232
+ // @param str [String] a string previously returned from {#serialize}
233
+ // @raise [ArgumentError] if the string isn't a valid serialized bitmap
234
+ // @return [Bitmap32]
192
235
  static VALUE rb_roaring32_deserialize(VALUE self, VALUE str)
193
236
  {
237
+ StringValue(str);
238
+
194
239
  roaring_bitmap_t *bitmap = roaring_bitmap_portable_deserialize_safe(RSTRING_PTR(str), RSTRING_LEN(str));
240
+ RB_GC_GUARD(str);
241
+
242
+ if (!bitmap) {
243
+ rb_raise(rb_eArgError, "invalid Roaring::Bitmap32 serialization");
244
+ }
195
245
 
196
246
  return TypedData_Wrap_Struct(cRoaringBitmap32, &roaring_type, bitmap);
197
247
  }
198
248
 
249
+ // Provides statistics about the internal layout of the bitmap
250
+ // @return [Hash]
251
+ static VALUE rb_roaring32_statistics(VALUE self)
252
+ {
253
+ roaring_bitmap_t *data = get_bitmap(self);
254
+
255
+ roaring_statistics_t stat;
256
+
257
+ roaring_bitmap_statistics(data, &stat);
258
+
259
+ VALUE ret = rb_hash_new();
260
+ #define ADD_STAT(name) \
261
+ rb_hash_aset(ret, rb_id2sym(rb_intern(#name)), ULL2NUM(stat.name))
262
+
263
+ ADD_STAT(n_containers);
264
+ ADD_STAT(n_array_containers);
265
+ ADD_STAT(n_run_containers);
266
+ ADD_STAT(n_bitset_containers);
267
+ ADD_STAT(n_values_array_containers);
268
+ ADD_STAT(n_values_run_containers);
269
+ ADD_STAT(n_values_bitset_containers);
270
+ ADD_STAT(n_bytes_array_containers);
271
+ ADD_STAT(n_bytes_run_containers);
272
+ ADD_STAT(n_bytes_bitset_containers);
273
+ ADD_STAT(max_value);
274
+ ADD_STAT(min_value);
275
+ // ADD_STAT(sum_value); // deprecated, skipped
276
+ ADD_STAT(cardinality);
277
+
278
+ #undef ADD_STAT
279
+
280
+ return ret;
281
+ }
282
+
199
283
  typedef roaring_bitmap_t *binary_func(const roaring_bitmap_t *, const roaring_bitmap_t *);
200
284
  static VALUE rb_roaring32_binary_op(VALUE self, VALUE other, binary_func func) {
201
285
  roaring_bitmap_t *self_data = get_bitmap(self);
@@ -206,6 +290,16 @@ static VALUE rb_roaring32_binary_op(VALUE self, VALUE other, binary_func func) {
206
290
  return TypedData_Wrap_Struct(cRoaringBitmap32, &roaring_type, result);
207
291
  }
208
292
 
293
+ typedef void binary_func_inplace(roaring_bitmap_t *, const roaring_bitmap_t *);
294
+ static VALUE rb_roaring32_binary_op_inplace(VALUE self, VALUE other, binary_func_inplace func) {
295
+ roaring_bitmap_t *self_data = get_bitmap(self);
296
+ roaring_bitmap_t *other_data = get_bitmap(other);
297
+
298
+ func(self_data, other_data);
299
+
300
+ return self;
301
+ }
302
+
209
303
  typedef bool binary_func_bool(const roaring_bitmap_t *, const roaring_bitmap_t *);
210
304
  static VALUE rb_roaring32_binary_op_bool(VALUE self, VALUE other, binary_func_bool func) {
211
305
  roaring_bitmap_t *self_data = get_bitmap(self);
@@ -215,42 +309,85 @@ static VALUE rb_roaring32_binary_op_bool(VALUE self, VALUE other, binary_func_bo
215
309
  return RBOOL(result);
216
310
  }
217
311
 
312
+ // Inplace version of {and}
313
+ // @return [self] the modified Bitmap
314
+ static VALUE rb_roaring32_and_inplace(VALUE self, VALUE other)
315
+ {
316
+ return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_and_inplace);
317
+ }
318
+
319
+ // Inplace version of {or}
320
+ // @return [self] the modified Bitmap
321
+ static VALUE rb_roaring32_or_inplace(VALUE self, VALUE other)
322
+ {
323
+ return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_or_inplace);
324
+ }
325
+
326
+ // Inplace version of {xor}
327
+ // @return [self] the modified Bitmap
328
+ static VALUE rb_roaring32_xor_inplace(VALUE self, VALUE other)
329
+ {
330
+ return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_xor_inplace);
331
+ }
332
+
333
+ // Inplace version of {andnot}
334
+ // @return [self] the modified Bitmap
335
+ static VALUE rb_roaring32_andnot_inplace(VALUE self, VALUE other)
336
+ {
337
+ return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_andnot_inplace);
338
+ }
218
339
 
340
+ // Computes the intersection between two bitmaps
341
+ // @return [Bitmap32] a new bitmap containing all elements in both `self` and `other`
219
342
  static VALUE rb_roaring32_and(VALUE self, VALUE other)
220
343
  {
221
344
  return rb_roaring32_binary_op(self, other, roaring_bitmap_and);
222
345
  }
223
346
 
347
+ // Computes the union between two bitmaps
348
+ // @return [Bitmap32] a new bitmap containing all elements in either `self` or `other`
224
349
  static VALUE rb_roaring32_or(VALUE self, VALUE other)
225
350
  {
226
351
  return rb_roaring32_binary_op(self, other, roaring_bitmap_or);
227
352
  }
228
353
 
354
+ // Computes the exclusive or between two bitmaps
355
+ // @return [Bitmap32] a new bitmap containing all elements in one of `self` or `other`, but not both
229
356
  static VALUE rb_roaring32_xor(VALUE self, VALUE other)
230
357
  {
231
358
  return rb_roaring32_binary_op(self, other, roaring_bitmap_xor);
232
359
  }
233
360
 
361
+ // Computes the difference between two bitmaps
362
+ // @return [Bitmap32] a new bitmap containing all elements in `self`, but not in `other`
234
363
  static VALUE rb_roaring32_andnot(VALUE self, VALUE other)
235
364
  {
236
365
  return rb_roaring32_binary_op(self, other, roaring_bitmap_andnot);
237
366
  }
238
367
 
368
+ // Compare equality between two bitmaps
369
+ // @return [Boolean] `true` if both bitmaps contain all the same elements, otherwise `false`
239
370
  static VALUE rb_roaring32_eq(VALUE self, VALUE other)
240
371
  {
241
372
  return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_equals);
242
373
  }
243
374
 
375
+ // Check if `self` is a strict subset of `other`. A strict subset requires every element in `self` is also in `other`, but they aren't exactly equal.
376
+ // @return [Boolean] `true` if `self` is a strict subset of `other`, otherwise `false`
244
377
  static VALUE rb_roaring32_lt(VALUE self, VALUE other)
245
378
  {
246
379
  return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_is_strict_subset);
247
380
  }
248
381
 
382
+ // Check if `self` is a (non-strict) subset of `other`. A subset requires that every element in `self` is also in `other`. They may be equal.
383
+ // @return [Boolean] `true` if `self` is a subset of `other`, otherwise `false`
249
384
  static VALUE rb_roaring32_lte(VALUE self, VALUE other)
250
385
  {
251
386
  return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_is_subset);
252
387
  }
253
388
 
389
+ // Checks whether `self` intersects `other`
390
+ // @return [Boolean] `true` if `self` intersects `other`, otherwise `false`
254
391
  static VALUE rb_roaring32_intersect_p(VALUE self, VALUE other)
255
392
  {
256
393
  return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_intersect);
@@ -267,17 +404,22 @@ rb_roaring32_init(void)
267
404
  rb_define_method(cRoaringBitmap32, "cardinality", rb_roaring32_cardinality, 0);
268
405
  rb_define_method(cRoaringBitmap32, "add", rb_roaring32_add, 1);
269
406
  rb_define_method(cRoaringBitmap32, "add?", rb_roaring32_add_p, 1);
270
- rb_define_method(cRoaringBitmap32, "<<", rb_roaring32_add, 1);
407
+ rb_define_method(cRoaringBitmap32, "add_range_closed", rb_roaring32_add_range_closed, 2);
271
408
  rb_define_method(cRoaringBitmap32, "remove", rb_roaring32_remove, 1);
272
409
  rb_define_method(cRoaringBitmap32, "remove?", rb_roaring32_remove_p, 1);
273
410
  rb_define_method(cRoaringBitmap32, "include?", rb_roaring32_include_p, 1);
274
411
  rb_define_method(cRoaringBitmap32, "each", rb_roaring32_each, 0);
275
412
  rb_define_method(cRoaringBitmap32, "[]", rb_roaring32_aref, 1);
276
413
 
277
- rb_define_method(cRoaringBitmap32, "&", rb_roaring32_and, 1);
278
- rb_define_method(cRoaringBitmap32, "|", rb_roaring32_or, 1);
279
- rb_define_method(cRoaringBitmap32, "^", rb_roaring32_xor, 1);
280
- rb_define_method(cRoaringBitmap32, "-", rb_roaring32_andnot, 1);
414
+ rb_define_method(cRoaringBitmap32, "and!", rb_roaring32_and_inplace, 1);
415
+ rb_define_method(cRoaringBitmap32, "or!", rb_roaring32_or_inplace, 1);
416
+ rb_define_method(cRoaringBitmap32, "xor!", rb_roaring32_xor_inplace, 1);
417
+ rb_define_method(cRoaringBitmap32, "andnot!", rb_roaring32_andnot_inplace, 1);
418
+
419
+ rb_define_method(cRoaringBitmap32, "and", rb_roaring32_and, 1);
420
+ rb_define_method(cRoaringBitmap32, "or", rb_roaring32_or, 1);
421
+ rb_define_method(cRoaringBitmap32, "xor", rb_roaring32_xor, 1);
422
+ rb_define_method(cRoaringBitmap32, "andnot", rb_roaring32_andnot, 1);
281
423
 
282
424
  rb_define_method(cRoaringBitmap32, "==", rb_roaring32_eq, 1);
283
425
  rb_define_method(cRoaringBitmap32, "<", rb_roaring32_lt, 1);
@@ -288,6 +430,7 @@ rb_roaring32_init(void)
288
430
  rb_define_method(cRoaringBitmap32, "max", rb_roaring32_max, 0);
289
431
 
290
432
  rb_define_method(cRoaringBitmap32, "run_optimize", rb_roaring32_run_optimize, 0);
433
+ rb_define_method(cRoaringBitmap32, "statistics", rb_roaring32_statistics, 0);
291
434
 
292
435
  rb_define_method(cRoaringBitmap32, "serialize", rb_roaring32_serialize, 0);
293
436
  rb_define_singleton_method(cRoaringBitmap32, "deserialize", rb_roaring32_deserialize, 1);
@@ -56,7 +56,7 @@ static VALUE rb_roaring64_replace(VALUE self, VALUE other) {
56
56
  // FIXME: Very likely a newer version of CRoaring will have
57
57
  //roaring64_bitmap_overwrite(self_data, other_data);
58
58
 
59
- roaring64_bitmap_remove_range_closed(self_data, 0, UINT64_MAX);
59
+ roaring64_bitmap_clear(self_data);
60
60
  roaring64_bitmap_or_inplace(self_data, other_data);
61
61
 
62
62
  return self;
@@ -86,6 +86,18 @@ static VALUE rb_roaring64_add_p(VALUE self, VALUE val)
86
86
  return roaring64_bitmap_add_checked(data, num) ? self : Qnil;
87
87
  }
88
88
 
89
+ static VALUE rb_roaring64_add_range_closed(VALUE self, VALUE minv, VALUE maxv)
90
+ {
91
+ roaring64_bitmap_t *data = get_bitmap(self);
92
+
93
+ uint64_t min = NUM2UINT64(minv);
94
+ uint64_t max = NUM2UINT64(maxv);
95
+
96
+ roaring64_bitmap_add_range_closed(data, min, max);
97
+
98
+ return self;
99
+ }
100
+
89
101
  static VALUE rb_roaring64_remove(VALUE self, VALUE val)
90
102
  {
91
103
  roaring64_bitmap_t *data = get_bitmap(self);
@@ -120,8 +132,7 @@ static VALUE rb_roaring64_empty_p(VALUE self)
120
132
  static VALUE rb_roaring64_clear(VALUE self)
121
133
  {
122
134
  roaring64_bitmap_t *data = get_bitmap(self);
123
- // roaring64_bitmap_clear(data); // Doesn't exist yet in 4.0.0
124
- roaring64_bitmap_remove_range_closed(data, 0, UINT64_MAX);
135
+ roaring64_bitmap_clear(data);
125
136
  return self;
126
137
  }
127
138
 
@@ -197,11 +208,50 @@ static VALUE rb_roaring64_serialize(VALUE self)
197
208
 
198
209
  static VALUE rb_roaring64_deserialize(VALUE self, VALUE str)
199
210
  {
211
+ StringValue(str);
212
+
200
213
  roaring64_bitmap_t *bitmap = roaring64_bitmap_portable_deserialize_safe(RSTRING_PTR(str), RSTRING_LEN(str));
214
+ RB_GC_GUARD(str);
215
+
216
+ if (!bitmap) {
217
+ rb_raise(rb_eArgError, "invalid Roaring::Bitmap64 serialization");
218
+ }
201
219
 
202
220
  return TypedData_Wrap_Struct(cRoaringBitmap64, &roaring64_type, bitmap);
203
221
  }
204
222
 
223
+ static VALUE rb_roaring64_statistics(VALUE self)
224
+ {
225
+ roaring64_bitmap_t *data = get_bitmap(self);
226
+
227
+ roaring64_statistics_t stat;
228
+
229
+ roaring64_bitmap_statistics(data, &stat);
230
+
231
+ VALUE ret = rb_hash_new();
232
+ #define ADD_STAT(name) \
233
+ rb_hash_aset(ret, rb_id2sym(rb_intern(#name)), ULL2NUM(stat.name))
234
+
235
+ ADD_STAT(n_containers);
236
+ ADD_STAT(n_array_containers);
237
+ ADD_STAT(n_run_containers);
238
+ ADD_STAT(n_bitset_containers);
239
+ ADD_STAT(n_values_array_containers);
240
+ ADD_STAT(n_values_run_containers);
241
+ ADD_STAT(n_values_bitset_containers);
242
+ ADD_STAT(n_bytes_array_containers);
243
+ ADD_STAT(n_bytes_run_containers);
244
+ ADD_STAT(n_bytes_bitset_containers);
245
+ ADD_STAT(max_value);
246
+ ADD_STAT(min_value);
247
+ // ADD_STAT(sum_value); // deprecated, skipped
248
+ ADD_STAT(cardinality);
249
+
250
+ #undef ADD_STAT
251
+
252
+ return ret;
253
+ }
254
+
205
255
  typedef roaring64_bitmap_t *binary_func(const roaring64_bitmap_t *, const roaring64_bitmap_t *);
206
256
  static VALUE rb_roaring64_binary_op(VALUE self, VALUE other, binary_func func) {
207
257
  roaring64_bitmap_t *self_data = get_bitmap(self);
@@ -212,6 +262,16 @@ static VALUE rb_roaring64_binary_op(VALUE self, VALUE other, binary_func func) {
212
262
  return TypedData_Wrap_Struct(cRoaringBitmap64, &roaring64_type, result);
213
263
  }
214
264
 
265
+ typedef void binary_func_inplace(roaring64_bitmap_t *, const roaring64_bitmap_t *);
266
+ static VALUE rb_roaring64_binary_op_inplace(VALUE self, VALUE other, binary_func_inplace func) {
267
+ roaring64_bitmap_t *self_data = get_bitmap(self);
268
+ roaring64_bitmap_t *other_data = get_bitmap(other);
269
+
270
+ func(self_data, other_data);
271
+
272
+ return self;
273
+ }
274
+
215
275
  typedef bool binary_func_bool(const roaring64_bitmap_t *, const roaring64_bitmap_t *);
216
276
  static VALUE rb_roaring64_binary_op_bool(VALUE self, VALUE other, binary_func_bool func) {
217
277
  roaring64_bitmap_t *self_data = get_bitmap(self);
@@ -221,6 +281,25 @@ static VALUE rb_roaring64_binary_op_bool(VALUE self, VALUE other, binary_func_bo
221
281
  return RBOOL(result);
222
282
  }
223
283
 
284
+ static VALUE rb_roaring64_and_inplace(VALUE self, VALUE other)
285
+ {
286
+ return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_and_inplace);
287
+ }
288
+
289
+ static VALUE rb_roaring64_or_inplace(VALUE self, VALUE other)
290
+ {
291
+ return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_or_inplace);
292
+ }
293
+
294
+ static VALUE rb_roaring64_xor_inplace(VALUE self, VALUE other)
295
+ {
296
+ return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_xor_inplace);
297
+ }
298
+
299
+ static VALUE rb_roaring64_andnot_inplace(VALUE self, VALUE other)
300
+ {
301
+ return rb_roaring64_binary_op_inplace(self, other, roaring64_bitmap_andnot_inplace);
302
+ }
224
303
 
225
304
  static VALUE rb_roaring64_and(VALUE self, VALUE other)
226
305
  {
@@ -273,6 +352,7 @@ rb_roaring64_init(void)
273
352
  rb_define_method(cRoaringBitmap64, "cardinality", rb_roaring64_cardinality, 0);
274
353
  rb_define_method(cRoaringBitmap64, "add", rb_roaring64_add, 1);
275
354
  rb_define_method(cRoaringBitmap64, "add?", rb_roaring64_add_p, 1);
355
+ rb_define_method(cRoaringBitmap64, "add_range_closed", rb_roaring64_add_range_closed, 2);
276
356
  rb_define_method(cRoaringBitmap64, "<<", rb_roaring64_add, 1);
277
357
  rb_define_method(cRoaringBitmap64, "remove", rb_roaring64_remove, 1);
278
358
  rb_define_method(cRoaringBitmap64, "remove?", rb_roaring64_remove_p, 1);
@@ -280,10 +360,15 @@ rb_roaring64_init(void)
280
360
  rb_define_method(cRoaringBitmap64, "each", rb_roaring64_each, 0);
281
361
  rb_define_method(cRoaringBitmap64, "[]", rb_roaring64_aref, 1);
282
362
 
283
- rb_define_method(cRoaringBitmap64, "&", rb_roaring64_and, 1);
284
- rb_define_method(cRoaringBitmap64, "|", rb_roaring64_or, 1);
285
- rb_define_method(cRoaringBitmap64, "^", rb_roaring64_xor, 1);
286
- rb_define_method(cRoaringBitmap64, "-", rb_roaring64_andnot, 1);
363
+ rb_define_method(cRoaringBitmap64, "and!", rb_roaring64_and_inplace, 1);
364
+ rb_define_method(cRoaringBitmap64, "or!", rb_roaring64_or_inplace, 1);
365
+ rb_define_method(cRoaringBitmap64, "xor!", rb_roaring64_xor_inplace, 1);
366
+ rb_define_method(cRoaringBitmap64, "andnot!", rb_roaring64_andnot_inplace, 1);
367
+
368
+ rb_define_method(cRoaringBitmap64, "and", rb_roaring64_and, 1);
369
+ rb_define_method(cRoaringBitmap64, "or", rb_roaring64_or, 1);
370
+ rb_define_method(cRoaringBitmap64, "xor", rb_roaring64_xor, 1);
371
+ rb_define_method(cRoaringBitmap64, "andnot", rb_roaring64_andnot, 1);
287
372
 
288
373
  rb_define_method(cRoaringBitmap64, "==", rb_roaring64_eq, 1);
289
374
  rb_define_method(cRoaringBitmap64, "<", rb_roaring64_lt, 1);
@@ -294,6 +379,7 @@ rb_roaring64_init(void)
294
379
  rb_define_method(cRoaringBitmap64, "max", rb_roaring64_max, 0);
295
380
 
296
381
  rb_define_method(cRoaringBitmap64, "run_optimize", rb_roaring64_run_optimize, 0);
382
+ rb_define_method(cRoaringBitmap64, "statistics", rb_roaring64_statistics, 0);
297
383
 
298
384
  rb_define_method(cRoaringBitmap64, "serialize", rb_roaring64_serialize, 0);
299
385
  rb_define_singleton_method(cRoaringBitmap64, "deserialize", rb_roaring64_deserialize, 1);