diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..e575012 --- /dev/null +++ b/.yardopts @@ -0,0 +1 @@ +--embed-mixins --no-private diff --git a/Gemfile b/Gemfile index db7a91b..72da1e8 100644 --- a/Gemfile +++ b/Gemfile @@ -11,3 +11,5 @@ gem "rake-compiler" gem "debug" gem "minitest", "~> 5.0" + +gem "yard" diff --git a/Gemfile.lock b/Gemfile.lock index 78b8ef3..6889829 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,6 +23,7 @@ GEM reline (0.3.1) io-console (~> 0.5) singleton (0.1.1) + yard (0.9.36) PLATFORMS arm64-darwin-23 @@ -35,6 +36,7 @@ DEPENDENCIES rake (~> 13.0) rake-compiler roaring! + yard BUNDLED WITH 2.3.4 diff --git a/Rakefile b/Rakefile index 903cc7d..978c7b0 100644 --- a/Rakefile +++ b/Rakefile @@ -3,6 +3,12 @@ require "bundler/gem_tasks" require "rake/testtask" +require "yard" + +YARD::Rake::YardocTask.new do |t| + t.files = ["lib/**/*.rb", "ext/**/*.c"] +end + Rake::TestTask.new(:test) do |t| t.libs << "test" t.libs << "lib" diff --git a/ext/roaring/bitmap32.c b/ext/roaring/bitmap32.c index 15cde89..a1a1386 100644 --- a/ext/roaring/bitmap32.c +++ b/ext/roaring/bitmap32.c @@ -48,6 +48,7 @@ static roaring_bitmap_t *get_bitmap(VALUE obj) { return bitmap; } +// Replaces the contents of `self` with another bitmap static VALUE rb_roaring32_replace(VALUE self, VALUE other) { roaring_bitmap_t *self_data = get_bitmap(self); roaring_bitmap_t *other_data = get_bitmap(other); @@ -57,6 +58,7 @@ static VALUE rb_roaring32_replace(VALUE self, VALUE other) { return self; } +// @return [Integer] the number of elements in the bitmap static VALUE rb_roaring32_cardinality(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); @@ -64,6 +66,8 @@ static VALUE rb_roaring32_cardinality(VALUE self) return ULONG2NUM(cardinality); } +// Adds an element from the bitmap +// @param val [Integer] the value to add static VALUE rb_roaring32_add(VALUE self, VALUE val) { roaring_bitmap_t *data = get_bitmap(self); @@ -73,6 +77,9 @@ static VALUE rb_roaring32_add(VALUE self, VALUE val) return self; } +// Adds an element from the bitmap +// @see {add} +// @return `self` if value was add, `nil` if value was already in the bitmap static VALUE rb_roaring32_add_p(VALUE self, VALUE val) { roaring_bitmap_t *data = get_bitmap(self); @@ -81,6 +88,7 @@ static VALUE rb_roaring32_add_p(VALUE self, VALUE val) return roaring_bitmap_add_checked(data, num) ? self : Qnil; } +// Removes an element from the bitmap static VALUE rb_roaring32_remove(VALUE self, VALUE val) { roaring_bitmap_t *data = get_bitmap(self); @@ -90,6 +98,10 @@ static VALUE rb_roaring32_remove(VALUE self, VALUE val) return self; } +// Removes an element from the bitmap +// +// @see {remove} +// @return [self,nil] `self` if value was removed, `nil` if the value wasn't in the bitmap static VALUE rb_roaring32_remove_p(VALUE self, VALUE val) { roaring_bitmap_t *data = get_bitmap(self); @@ -98,6 +110,7 @@ static VALUE rb_roaring32_remove_p(VALUE self, VALUE val) return roaring_bitmap_remove_checked(data, num) ? self : Qnil; } +// @return [Boolean] `true` if the bitmap is contains `val`, otherwise `false` static VALUE rb_roaring32_include_p(VALUE self, VALUE val) { roaring_bitmap_t *data = get_bitmap(self); @@ -106,12 +119,14 @@ static VALUE rb_roaring32_include_p(VALUE self, VALUE val) return RBOOL(roaring_bitmap_contains(data, num)); } +// @return [Boolean] `true` if the bitmap is empty, otherwise `false` static VALUE rb_roaring32_empty_p(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); return RBOOL(roaring_bitmap_is_empty(data)); } +// Removes all elements from the bitmap static VALUE rb_roaring32_clear(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); @@ -124,6 +139,8 @@ bool rb_roaring32_each_i(uint32_t value, void *param) { return true; // iterate till the end } +// Iterates over every element in the bitmap +// @return [self] static VALUE rb_roaring32_each(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); @@ -131,6 +148,8 @@ static VALUE rb_roaring32_each(VALUE self) return self; } +// Find the nth smallest integer in the bitmap +// @return [Integer,nil] The nth integer in the bitmap, or `nil` if `rankv` is `>= cardinality` static VALUE rb_roaring32_aref(VALUE self, VALUE rankv) { roaring_bitmap_t *data = get_bitmap(self); @@ -146,6 +165,8 @@ static VALUE rb_roaring32_aref(VALUE self, VALUE rankv) return self; } +// Find the smallest integer in the bitmap +// @return [Integer,nil] The smallest integer in the bitmap, or `nil` if it is empty static VALUE rb_roaring32_min(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); @@ -158,6 +179,8 @@ static VALUE rb_roaring32_min(VALUE self) } } +// Find the largest integer in the bitmap +// @return [Integer,nil] The largest integer in the bitmap, or `nil` if it is empty static VALUE rb_roaring32_max(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); @@ -170,12 +193,16 @@ static VALUE rb_roaring32_max(VALUE self) } } +// Attemps to internally optimize the representation of bitmap by finding runs, consecutive sequences of integers. +// @return [Boolean] whether the result has at least one run container static VALUE rb_roaring32_run_optimize(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); return RBOOL(roaring_bitmap_run_optimize(data)); } +// Serializes a bitmap into a string +// @return [string] static VALUE rb_roaring32_serialize(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); @@ -189,6 +216,8 @@ static VALUE rb_roaring32_serialize(VALUE self) return str; } +// Loads a previously serialized bitmap +// @return [Bitmap32] static VALUE rb_roaring32_deserialize(VALUE self, VALUE str) { roaring_bitmap_t *bitmap = roaring_bitmap_portable_deserialize_safe(RSTRING_PTR(str), RSTRING_LEN(str)); @@ -196,6 +225,8 @@ static VALUE rb_roaring32_deserialize(VALUE self, VALUE str) return TypedData_Wrap_Struct(cRoaringBitmap32, &roaring_type, bitmap); } +// Provides statistics about the internal layout of the bitmap +// @return [Hash] static VALUE rb_roaring32_statistics(VALUE self) { roaring_bitmap_t *data = get_bitmap(self); @@ -257,61 +288,85 @@ static VALUE rb_roaring32_binary_op_bool(VALUE self, VALUE other, binary_func_bo return RBOOL(result); } +// Inplace version of {and} +// @return [self] the modified Bitmap static VALUE rb_roaring32_and_inplace(VALUE self, VALUE other) { return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_and_inplace); } +// Inplace version of {or} +// @return [self] the modified Bitmap static VALUE rb_roaring32_or_inplace(VALUE self, VALUE other) { return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_or_inplace); } +// Inplace version of {xor} +// @return [self] the modified Bitmap static VALUE rb_roaring32_xor_inplace(VALUE self, VALUE other) { return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_xor_inplace); } +// Inplace version of {andnot} +// @return [self] the modified Bitmap static VALUE rb_roaring32_andnot_inplace(VALUE self, VALUE other) { return rb_roaring32_binary_op_inplace(self, other, roaring_bitmap_andnot_inplace); } +// Computes the intersection between two bitmaps +// @return [Bitmap32] a new bitmap containing all elements in both `self` and `other` static VALUE rb_roaring32_and(VALUE self, VALUE other) { return rb_roaring32_binary_op(self, other, roaring_bitmap_and); } +// Computes the union between two bitmaps +// @return [Bitmap32] a new bitmap containing all elements in either `self` or `other` static VALUE rb_roaring32_or(VALUE self, VALUE other) { return rb_roaring32_binary_op(self, other, roaring_bitmap_or); } +// Computes the exclusive or between two bitmaps +// @return [Bitmap32] a new bitmap containing all elements in one of `self` or `other`, but not both static VALUE rb_roaring32_xor(VALUE self, VALUE other) { return rb_roaring32_binary_op(self, other, roaring_bitmap_xor); } +// Computes the difference between two bitmaps +// @return [Bitmap32] a new bitmap containing all elements in `self`, but not in `other` static VALUE rb_roaring32_andnot(VALUE self, VALUE other) { return rb_roaring32_binary_op(self, other, roaring_bitmap_andnot); } +// Compare equality between two bitmaps +// @return [Boolean] `true` if both bitmaps contain all the same elements, otherwise `false` static VALUE rb_roaring32_eq(VALUE self, VALUE other) { return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_equals); } +// 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. +// @return [Boolean] `true` if `self` is a strict subset of `other`, otherwise `false` static VALUE rb_roaring32_lt(VALUE self, VALUE other) { return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_is_strict_subset); } +// 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. +// @return [Boolean] `true` if `self` is a subset of `other`, otherwise `false` static VALUE rb_roaring32_lte(VALUE self, VALUE other) { return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_is_subset); } +// Checks whether `self` intersects `other` +// @return [Boolean] `true` if `self` intersects `other`, otherwise `false` static VALUE rb_roaring32_intersect_p(VALUE self, VALUE other) { return rb_roaring32_binary_op_bool(self, other, roaring_bitmap_intersect); @@ -328,7 +383,6 @@ rb_roaring32_init(void) rb_define_method(cRoaringBitmap32, "cardinality", rb_roaring32_cardinality, 0); rb_define_method(cRoaringBitmap32, "add", rb_roaring32_add, 1); rb_define_method(cRoaringBitmap32, "add?", rb_roaring32_add_p, 1); - rb_define_method(cRoaringBitmap32, "<<", rb_roaring32_add, 1); rb_define_method(cRoaringBitmap32, "remove", rb_roaring32_remove, 1); rb_define_method(cRoaringBitmap32, "remove?", rb_roaring32_remove_p, 1); rb_define_method(cRoaringBitmap32, "include?", rb_roaring32_include_p, 1); diff --git a/lib/roaring.rb b/lib/roaring.rb index 256159a..a6490a9 100644 --- a/lib/roaring.rb +++ b/lib/roaring.rb @@ -8,41 +8,67 @@ module Roaring class Error < StandardError; end module BitmapCommon - def self.included(base) - super - - base.extend ClassMethods - - base.alias_method :size, :cardinality - base.alias_method :length, :cardinality - base.alias_method :count, :cardinality - - base.alias_method :&, :and - base.alias_method :|, :or - base.alias_method :^, :xor - base.alias_method :-, :andnot - base.alias_method :+, :or - base.alias_method :union, :or - base.alias_method :intersection, :and - base.alias_method :difference, :andnot - - base.alias_method :delete, :remove - base.alias_method :delete?, :remove? - - base.alias_method :first, :min - base.alias_method :last, :max - - base.alias_method :eql?, :== - - base.alias_method :===, :include? - - base.alias_method :subset?, :<= - base.alias_method :proper_subset?, :< - base.alias_method :superset?, :>= - base.alias_method :proper_superset?, :> - end - module ClassMethods + # @private + # @!macro [attach] property + # @!parse alias_method :<<, :add + # + # @!parse alias_method :size, :cardinality + # @!parse alias_method :length, :cardinality + # @!parse alias_method :count, :cardinality + # + # @!parse alias_method :&, :and + # @!parse alias_method :|, :or + # @!parse alias_method :^, :xor + # @!parse alias_method :-, :andnot + # @!parse alias_method :+, :or + # @!parse alias_method :union, :or + # @!parse alias_method :intersection, :and + # @!parse alias_method :difference, :andnot + # + # @!parse alias_method :delete, :remove + # @!parse alias_method :delete?, :remove? + # + # @!parse alias_method :first, :min + # @!parse alias_method :last, :max + # + # @!parse alias_method :eql?, :== + # + # @!parse alias_method :===, :include? + # + # @!parse alias_method :subset?, :<= + # @!parse alias_method :proper_subset?, :< + def define_roaring_aliases! + alias_method :<<, :add + + alias_method :size, :cardinality + alias_method :length, :cardinality + alias_method :count, :cardinality + + alias_method :&, :and + alias_method :|, :or + alias_method :^, :xor + alias_method :-, :andnot + alias_method :+, :or + alias_method :union, :or + alias_method :intersection, :and + alias_method :difference, :andnot + + alias_method :delete, :remove + alias_method :delete?, :remove? + + alias_method :first, :min + alias_method :last, :max + + alias_method :eql?, :== + + alias_method :===, :include? + + alias_method :subset?, :<= + alias_method :proper_subset?, :< + end + + # Convenience method for building a bitmap def [](*args) if args.size == 0 new @@ -78,14 +104,22 @@ def initialize_copy(other) replace(other) end - def >(other) - other < self + # Check if `self` is a superset of `other`. A superset requires that `self` contain all of `other`'s elemtents. They may be equal. + # @return [Boolean] `true` if `self` is a strict subset of `other`, otherwise `false` + def superset?(other) + other <= self end - def >=(other) - other <= self + # Check if `self` is a strict superset of `other`. A strict superset requires that `self` contain all of `other`'s elemtents, but that they aren't exactly equal. + # @return [Boolean] `true` if `self` is a strict subset of `other`, otherwise `false` + def proper_superset?(other) + other < self end + alias_method :>=, :superset? + alias_method :>, :proper_superset? + + # @return [Integer] Returns 0 if the bitmaps are equal, -1 / +1 if the set is a subset / superset of the given set, or nil if they both have unique elements. def <=>(other) if self == other 0 @@ -114,6 +148,11 @@ def to_set ::Set.new(to_a) end + # @example Small bitmap + # Roaring::Bitmap32[1,2,3].inspect #=> "#" + # @example Large bitmap + # Roaring::Bitmap32[1..1000].inspect #=> "#" + # @return [String] a programmer-readable representation of the bitmap def inspect cardinality = self.cardinality if cardinality < 64 @@ -126,6 +165,9 @@ def inspect class Bitmap32 include BitmapCommon + extend BitmapCommon::ClassMethods + + define_roaring_aliases! MIN = 0 MAX = (2**32) - 1 @@ -134,6 +176,9 @@ class Bitmap32 class Bitmap64 include BitmapCommon + extend BitmapCommon::ClassMethods + + define_roaring_aliases! MIN = 0 MAX = (2**64) - 1