class AutoC::Range::ForwardRange::ContiguousRange
@abstract
Constants
- OPTIONAL_OMP_H
Public Class Methods
new(iterable, visibility: :public, parallel: nil)
click to toggle source
Calls superclass method
AutoC::Range::new
# File lib/autoc/ranges.rb, line 392 def initialize(iterable, visibility: :public, parallel: nil) super(iterable, visibility:) @parallel = parallel end
Public Instance Methods
render_interface(stream)
click to toggle source
# File lib/autoc/ranges.rb, line 397 def render_interface(stream) if public? case @parallel when nil stream << %{ /** #{defgroup} #{brief} This is the range for contiguous data structures (vectors, strings etc.) It can be used the following way: @code{.c} for(#{signature} r = #{new}(&it); !#{empty}(&r); #{pop_front}(&r)) { ... } @endcode @see @ref Range @since 2.0 */ } when :openmp stream << %{ /** #{defgroup} #{brief} This is the range for contiguous data structures (vectors, strings etc.) The @ref #{new} and @ref #{custom_create} range constructors create OpenMP-aware range objects which account for parallel iteration in the way @code{.c} #pragma omp parallel for(#{signature} r = #{new}(&it); !#{empty}(&r); #{pop_front}(&r)) { ... } @endcode @see @ref Range @since 2.0 */ } end end if public? stream << %{ /** #{ingroup} @brief Opaque structure holding state of the contiguous container's range @since 2.0 */ } else stream << PRIVATE end stream << %{ typedef struct { #{iterable.element.lvalue} front; /**< @private */ #{iterable.element.lvalue} back; /**< @private */ } #{signature}; } end
Private Instance Methods
configure()
click to toggle source
Calls superclass method
AutoC::Range::ForwardRange::DirectAccessRange#configure
# File lib/autoc/ranges.rb, line 471 def configure super case @parallel when nil custom_create.configure do inline_code %{ assert(range); assert(iterable); range->front = #{_iterable.storage(iterable)}; range->back = #{_iterable.storage(iterable)} + #{_iterable.size.(iterable)} - 1; } end when :openmp dependencies << OPTIONAL_OMP_H custom_create.configure do inline_code %{ size_t size; #ifdef _OPENMP unsigned chunk_count; #endif assert(range); assert(iterable); size = #{_iterable.size.(iterable)}; #ifdef _OPENMP if(omp_in_parallel() && (chunk_count = omp_get_num_threads()) > 1) { int chunk_id = omp_get_thread_num(); size_t chunk_size = size / omp_get_num_threads(); range->front = #{_iterable.storage(iterable)} + chunk_id*chunk_size; range->back = #{_iterable.storage(iterable)} + ( chunk_id < chunk_count - 1 ? (chunk_id + 1)*chunk_size - 1 : size - 1 ); } else { #endif range->front = #{_iterable.storage(iterable)}; range->back = #{_iterable.storage(iterable)} + size - 1; #ifdef _OPENMP } #endif } end else raise "unsupported parallel range specifier #{@parallel}" end empty.configure do inline_code %{ assert(range); assert(range->front); assert(range->back); return range->front > range->back; } end pop_front.configure do dependencies << empty inline_code %{ assert(range); assert(range->front); assert(!#{empty.(range)}); ++range->front; } end pop_back.configure do dependencies << empty inline_code %{ assert(range); assert(range->back); assert(!#{empty.(range)}); --range->back; } end view_front.configure do dependencies << empty inline_code %{ assert(range); assert(range->front); assert(!#{empty.(range)}); return range->front; } end view_back.configure do dependencies << empty inline_code %{ assert(range); assert(range->back); assert(!#{empty.(range)}); return range->back; } end size.configure do dependencies << empty inline_code %{ assert(range); assert(range->front); assert(range->back); return #{empty.(range)} ? 0 : range->back - range->front + 1; } end view.configure do dependencies << check inline_code %{ assert(range); assert(#{check.(range, index)}); return range->front + index; } end end