Class: DataStructuresRMolinari::SegmentTree::CSegmentTreeTemplate
- Inherits:
-
Object
- Object
- DataStructuresRMolinari::SegmentTree::CSegmentTreeTemplate
- Defined in:
- lib/data_structures_rmolinari/segment_tree.rb,
ext/c_segment_tree_template/segment_tree_template.c
Overview
The underlying functionality of the Segment Tree data type, implemented in C as a Ruby extension.
See SegmentTreeTemplate for more information.
Implementation note
The functionality is entirely written in C. But we write the constructor in Ruby because keyword arguments are difficult to parse on the C side.
Instance Method Summary collapse
-
#c_initialize(combine, single_cell_array_val, size, identity) ⇒ Object
CSegmentTreeTemplate#c_initialize.
-
#initialize(combine:, single_cell_array_val:, size:, identity:) ⇒ CSegmentTreeTemplate
constructor
A new instance of CSegmentTreeTemplate.
-
#query_on(left, right) ⇒ Object
The desired value (max, sum, etc.) on the subinterval left..right.
-
#update_at(idx) ⇒ Object
Reflect the fact that the underlying array has been updated at the given idx.
Constructor Details
#initialize(combine:, single_cell_array_val:, size:, identity:) ⇒ CSegmentTreeTemplate
Returns a new instance of CSegmentTreeTemplate.
120 121 122 123 |
# File 'lib/data_structures_rmolinari/segment_tree.rb', line 120 def initialize(combine:, single_cell_array_val:, size:, identity:) # having sorted out the keyword arguments, pass them more easily to the C layer. c_initialize(combine, single_cell_array_val, size, identity) end |
Instance Method Details
#c_initialize(combine, single_cell_array_val, size, identity) ⇒ Object
CSegmentTreeTemplate#c_initialize.
(see CSegmentTreeTemplate#initialize).
309 310 311 312 |
# File 'ext/c_segment_tree_template/segment_tree_template.c', line 309
static VALUE segment_tree_init(VALUE self, VALUE combine, VALUE single_cell_array_val, VALUE size, VALUE identity) {
setup(unwrapped(self), combine, single_cell_array_val, size, identity);
return self;
}
|
#query_on(left, right) ⇒ Object
The desired value (max, sum, etc.) on the subinterval left..right.
It must be that left..right is contained in 0…size.
The type of the return value depends on the concrete instance of the segment tree. We return the identity element provided at construction time if the interval is empty.
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'ext/c_segment_tree_template/segment_tree_template.c', line 317
static VALUE segment_tree_query_on(VALUE self, VALUE left, VALUE right) {
segment_tree_data* seg_tree = unwrapped(self);
size_t c_left = checked_nonneg_fixnum(left);
size_t c_right = checked_nonneg_fixnum(right);
if (c_right >= seg_tree->size) {
rb_raise(eSharedDataError, "Bad query interval %lu..%lu (size = %lu)", c_left, c_right, seg_tree->size);
}
if (left > right) {
// empty interval.
return seg_tree->identity;
}
return determine_val(seg_tree, TREE_ROOT, c_left, c_right, 0, seg_tree->size - 1);
}
|
#update_at(idx) ⇒ Object
Reflect the fact that the underlying array has been updated at the given idx
Note that we don’t need the updated value itself. We get that by calling the lambda single_cell_array_val supplied at construction.
337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'ext/c_segment_tree_template/segment_tree_template.c', line 337
static VALUE segment_tree_update_at(VALUE self, VALUE idx) {
segment_tree_data *seg_tree = unwrapped(self);
size_t c_idx = checked_nonneg_fixnum(idx);
if (c_idx >= seg_tree->size) {
rb_raise(eSharedDataError, "Cannot update value at index %lu, size = %lu", c_idx, seg_tree->size);
}
update_val_at(seg_tree, c_idx, TREE_ROOT, 0, seg_tree->size - 1);
return Qnil;
}
|