1010#include " meta_data.hpp"
1111
1212#include " ../common/common.hpp"
13+ #include " ../common/counting_iterator.hpp"
1314#include " ../common/exception.hpp"
1415#include " ../common/iterator_facade.hpp"
16+ #include " ../common/typing.hpp"
1517
1618#include < algorithm>
1719#include < cassert>
1820#include < concepts>
1921#include < cstddef>
22+ #include < iterator>
2023#include < ranges>
2124#include < span>
2225#include < string>
2326#include < string_view>
2427#include < type_traits>
28+ #include < utility>
2529#include < vector>
2630
2731namespace power_grid_model {
@@ -216,6 +220,8 @@ template <dataset_type_tag dataset_type_> class Dataset {
216220 std::span<Indptr> indptr{};
217221 };
218222
223+ template <class StructType > using SpanRange = std::span<StructType>;
224+
219225 template <class StructType >
220226 using RangeObject = std::conditional_t <is_data_mutable_v<dataset_type>, mutable_range_object<StructType>,
221227 const_range_object<StructType>>;
@@ -452,7 +458,7 @@ template <dataset_type_tag dataset_type_> class Dataset {
452458 // get buffer by component type
453459 template <class type_getter , class ComponentType ,
454460 class StructType = DataStruct<typename type_getter::template type<ComponentType>>>
455- std::span <StructType> get_buffer_span (Idx scenario = invalid_index) const {
461+ SpanRange <StructType> get_buffer_span (Idx scenario = invalid_index) const {
456462 assert (scenario < batch_size ());
457463
458464 if (!is_batch () && scenario > 0 ) {
@@ -476,27 +482,17 @@ template <dataset_type_tag dataset_type_> class Dataset {
476482 return get_columnar_buffer_span_impl<StructType>(scenario, idx);
477483 }
478484
479- // get buffer by component type for all scenarios in vector span
485+ // get buffer by component type for all non-empty scenarios in vector span
480486 template <class type_getter , class ComponentType ,
481487 class StructType = DataStruct<typename type_getter::template type<ComponentType>>>
482- std::vector<std::span<StructType>> get_buffer_span_all_scenarios () const {
483- Idx const idx = find_component (ComponentType::name, false );
484- std::vector<std::span<StructType>> result (batch_size ());
485- for (Idx scenario{}; scenario != batch_size (); scenario++) {
486- result[scenario] = get_buffer_span_impl<StructType>(scenario, idx);
487- }
488- return result;
488+ std::vector<SpanRange<StructType>> get_buffer_span_all_scenarios () const {
489+ return get_buffer_span_all_scenarios_impl<type_getter, ComponentType, SpanRange>();
489490 }
490491
491492 template <class type_getter , class ComponentType ,
492493 class StructType = DataStruct<typename type_getter::template type<ComponentType>>>
493494 std::vector<RangeObject<StructType>> get_columnar_buffer_span_all_scenarios () const {
494- Idx const idx = find_component (ComponentType::name, false );
495- std::vector<RangeObject<StructType>> result (batch_size ());
496- for (Idx scenario{}; scenario != batch_size (); scenario++) {
497- result[scenario] = get_columnar_buffer_span_impl<StructType>(scenario, idx);
498- }
499- return result;
495+ return get_buffer_span_all_scenarios_impl<type_getter, ComponentType, RangeObject>();
500496 }
501497
502498 // get individual dataset from batch
@@ -559,7 +555,7 @@ template <dataset_type_tag dataset_type_> class Dataset {
559555
560556 template <class type_getter , class ComponentType , typename Func,
561557 class StructType = DataStruct<typename type_getter::template type<ComponentType>>>
562- requires std::invocable<Func, std::span <StructType>> && std::invocable<Func, RangeObject<StructType>>
558+ requires std::invocable<Func, SpanRange <StructType>> && std::invocable<Func, RangeObject<StructType>>
563559 auto for_each_component (Func&& func, Idx scenario = invalid_index) const {
564560 if (is_columnar (ComponentType::name)) {
565561 return std::forward<Func>(func)(get_columnar_buffer_span<type_getter, ComponentType, StructType>(scenario));
@@ -659,31 +655,53 @@ template <dataset_type_tag dataset_type_> class Dataset {
659655 std::begin (total_range) + info.elements_per_scenario * (scenario + 1 )};
660656 }
661657
662- // get non-empty row buffer
663- template <class StructType > std::span<StructType> get_buffer_span_impl (Idx scenario, Idx component_idx) const {
658+ template <typename StructType, template <typename > typename RangeType>
659+ requires std::ranges::view<RangeType<StructType>> &&
660+ (std::same_as<RangeType<StructType>, SpanRange<StructType>> ||
661+ std::same_as<RangeType<StructType>, RangeObject<StructType>>)
662+ auto get_buffer_view_impl (Idx scenario, Idx component_idx) const {
663+ using RangeType_ = RangeType<StructType>;
664+
664665 // return empty span if the component does not exist
665666 if (component_idx < 0 ) {
666- return {};
667+ return RangeType_ {};
667668 }
668669 // return span based on uniform or non-uniform buffer
669670 ComponentInfo const & info = dataset_info_.component_info [component_idx];
670671 Buffer const & buffer = buffers_[component_idx];
671- auto const ptr = reinterpret_cast <StructType*>(buffer.data );
672- return get_span_impl (std::span<StructType>{ptr, ptr + info.total_elements }, scenario, buffer, info);
672+
673+ if constexpr (std::same_as<RangeType_, SpanRange<StructType>>) {
674+ assert (is_row_based (buffer) || info.total_elements == 0 );
675+ auto const ptr = reinterpret_cast <StructType*>(buffer.data );
676+ return get_span_impl (RangeType_{ptr, ptr + info.total_elements }, scenario, buffer, info);
677+ } else if constexpr (std::same_as<RangeType_, RangeObject<StructType>>) {
678+ assert (is_columnar (buffer));
679+ return get_span_impl (RangeType_{info.total_elements , buffer.attributes }, scenario, buffer, info);
680+ } else {
681+ static_assert (false , " only span and RangeObject are supported" );
682+ }
683+ }
684+
685+ // get non-empty row buffer
686+ template <class StructType > SpanRange<StructType> get_buffer_span_impl (Idx scenario, Idx component_idx) const {
687+ return get_buffer_view_impl<StructType, SpanRange>(scenario, component_idx);
673688 }
674689
675690 // get non-empty columnar buffer
676691 template <class StructType >
677692 RangeObject<StructType> get_columnar_buffer_span_impl (Idx scenario, Idx component_idx) const {
678- // return empty span if the component does not exist
679- if (component_idx < 0 ) {
680- return {};
681- }
682- // return span based on uniform or non-uniform buffer
683- ComponentInfo const & info = dataset_info_.component_info [component_idx];
684- Buffer const & buffer = buffers_[component_idx];
685- assert (is_columnar (buffer));
686- return get_span_impl (RangeObject<StructType>{info.total_elements , buffer.attributes }, scenario, buffer, info);
693+ return get_buffer_view_impl<StructType, RangeObject>(scenario, component_idx);
694+ }
695+
696+ template <class type_getter , class ComponentType , template <typename > typename RangeType,
697+ typename StructType = DataStruct<typename type_getter::template type<ComponentType>>>
698+ requires std::ranges::view<RangeType<StructType>>
699+ std::vector<RangeType<StructType>> get_buffer_span_all_scenarios_impl () const {
700+ Idx const component_idx = find_component (ComponentType::name, false );
701+ return IdxRange{batch_size ()} | std::views::transform ([this , component_idx](Idx scenario) {
702+ return get_buffer_view_impl<StructType, RangeType>(scenario, component_idx);
703+ }) |
704+ std::ranges::to<std::vector>();
687705 }
688706};
689707
0 commit comments