Skip to content
Merged
115 changes: 78 additions & 37 deletions Framework/Core/include/Framework/ASoA.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,6 @@ template <typename D, typename... Cs>
struct TableMetadata {
using columns = framework::pack<Cs...>;
using persistent_columns_t = framework::selected_pack<soa::is_persistent_column_t, Cs...>;
using external_index_columns_t = framework::selected_pack<soa::is_external_index_t, Cs...>;
using internal_index_columns_t = framework::selected_pack<soa::is_self_index_t, Cs...>;

template <typename Key, typename... PCs>
static consteval std::array<bool, sizeof...(PCs)> getMap(framework::pack<PCs...>)
Expand Down Expand Up @@ -806,9 +804,6 @@ concept is_dynamic_column = requires(C& c) {
template <typename C>
concept is_marker_column = requires { &C::mark; };

template <typename T>
using is_dynamic_t = std::conditional_t<is_dynamic_column<T>, std::true_type, std::false_type>;

template <typename T>
concept is_column = is_persistent_column<T> || is_dynamic_column<T> || is_indexing_column<T> || is_marker_column<T>;

Expand Down Expand Up @@ -1031,16 +1026,27 @@ concept can_bind = requires(T&& t) {
template <typename... C>
concept has_index = (is_indexing_column<C> || ...);

template <is_index_column C>
requires(!is_self_index_column<C>)
consteval auto getBinding() -> typename C::binding_t
{
}

template <typename C>
consteval auto getBinding() -> void
{
}

template <typename D, typename O, typename IP, typename... C>
struct TableIterator : IP, C... {
public:
using self_t = TableIterator<D, O, IP, C...>;
using policy_t = IP;
using all_columns = framework::pack<C...>;
using persistent_columns_t = framework::selected_pack<soa::is_persistent_column_t, C...>;
using external_index_columns_t = framework::selected_pack<soa::is_external_index_t, C...>;
using internal_index_columns_t = framework::selected_pack<soa::is_self_index_t, C...>;
using bindings_pack_t = decltype([]<typename... Cs>(framework::pack<Cs...>) -> framework::pack<typename Cs::binding_t...> {}(external_index_columns_t{})); // decltype(extractBindings(external_index_columns_t{}));
using bindings_pack_t = decltype([]<typename... Cs>(framework::pack<Cs...>) {
return framework::pack<decltype(getBinding<Cs>())...>{};
}(all_columns{}));

TableIterator(arrow::ChunkedArray* columnData[sizeof...(C)], IP&& policy)
: IP{policy},
Expand Down Expand Up @@ -1133,7 +1139,13 @@ struct TableIterator : IP, C... {
template <typename... CL, typename TA>
void doSetCurrentIndex(framework::pack<CL...>, TA* current)
{
(CL::setCurrent(current), ...);
(framework::overloaded{
[&current, this]<is_index_column CI>
requires(!is_self_index_column<CI>)
() { CI::setCurrent(current); },
[]<typename CI>() {}}
.template operator()<CL>(),
...);
}

template <typename CL>
Expand All @@ -1145,43 +1157,63 @@ struct TableIterator : IP, C... {
template <typename... Cs>
auto getIndexBindingsImpl(framework::pack<Cs...>) const
{
return std::vector<o2::soa::Binding>{static_cast<Cs const&>(*this).getCurrentRaw()...};
std::vector<o2::soa::Binding> result;
(framework::overloaded{
[this, &result]<is_index_column CI>
requires(!is_self_index_column<CI>)
() mutable {
result.emplace_back(CI::getCurrentRaw());
},
[]<typename CI>() {}}
.template operator()<Cs>(),
...);
return result;
}

auto getIndexBindings() const
{
return getIndexBindingsImpl(external_index_columns_t{});
return getIndexBindingsImpl(all_columns{});
}

template <typename... TA>
void bindExternalIndices(TA*... current)
{
(doSetCurrentIndex(external_index_columns_t{}, current), ...);
(doSetCurrentIndex(all_columns{}, current), ...);
}

template <typename... Cs>
void doSetCurrentIndexRaw(framework::pack<Cs...> p, std::vector<o2::soa::Binding>&& ptrs)
{
(Cs::setCurrentRaw(ptrs[framework::has_type_at_v<Cs>(p)]), ...);
(framework::overloaded{
[&ptrs, p, this]<is_self_index_column CI>
requires(!is_self_index_column<CI>)
() { CI::setCurrentRaw(ptrs[framework::has_type_at_v<CI>(p)]); },
[]<typename CI>() {}}
.template operator()<Cs>(),
...);
}

template <typename... Cs, typename I>
void doSetCurrentInternal(framework::pack<Cs...>, I const* ptr)
{
o2::soa::Binding b;
b.bind(ptr);
(Cs::setCurrentRaw(b), ...);
(framework::overloaded{
[&ptr, &b, this]<is_self_index_column CI>() { CI::setCurrentRaw(b); },
[]<typename CI>() {}}
.template operator()<Cs>(),
...);
}

void bindExternalIndicesRaw(std::vector<o2::soa::Binding>&& ptrs)
{
doSetCurrentIndexRaw(external_index_columns_t{}, std::forward<std::vector<o2::soa::Binding>>(ptrs));
doSetCurrentIndexRaw(all_columns{}, std::forward<std::vector<o2::soa::Binding>>(ptrs));
}

template <typename I>
void bindInternalIndices(I const* table)
{
doSetCurrentInternal(internal_index_columns_t{}, table);
doSetCurrentInternal(all_columns{}, table);
}

private:
Expand Down Expand Up @@ -1365,25 +1397,37 @@ static constexpr std::string getLabelFromTypeForKey(std::string const& key)
template <typename B, typename... C>
consteval static bool hasIndexTo(framework::pack<C...>&&)
{
return (o2::soa::is_binding_compatible_v<B, typename C::binding_t>() || ...);
return (framework::overloaded{
[]<is_index_column CI>
requires(!is_self_index_column<CI>)
() { return o2::soa::is_binding_compatible_v<B, typename CI::binding_t>(); },
[]<typename CI>() { return false; }}
.template operator()<C>() ||
...);
}

template <typename B, typename... C>
consteval static bool hasSortedIndexTo(framework::pack<C...>&&)
{
return ((C::sorted && o2::soa::is_binding_compatible_v<B, typename C::binding_t>()) || ...);
return (framework::overloaded{
[]<is_index_column CI>
requires(!is_self_index_column<CI>)
() { return (CI::sorted && o2::soa::is_binding_compatible_v<B, typename CI::binding_t>()); },
[]<typename CI>() {}}
.template operator()<C>() ||
...);
}

template <typename B, typename Z>
consteval static bool relatedByIndex()
{
return hasIndexTo<B>(typename Z::table_t::external_index_columns_t{});
return hasIndexTo<B>(typename Z::table_t::columns_t{});
}

template <typename B, typename Z>
consteval static bool relatedBySortedIndex()
{
return hasSortedIndexTo<B>(typename Z::table_t::external_index_columns_t{});
return hasSortedIndexTo<B>(typename Z::table_t::columns_t{});
}
} // namespace o2::soa

Expand Down Expand Up @@ -1726,16 +1770,13 @@ class Table
using persistent_columns_t = decltype([]<typename... C>(framework::pack<C...>&&) -> framework::selected_pack<soa::is_persistent_column_t, C...> {}(columns_t{}));
using column_types = decltype([]<typename... C>(framework::pack<C...>) -> framework::pack<typename C::type...> {}(persistent_columns_t{}));

using external_index_columns_t = decltype([]<typename... C>(framework::pack<C...>&&) -> framework::selected_pack<soa::is_external_index_t, C...> {}(columns_t{}));
using internal_index_columns_t = decltype([]<typename... C>(framework::pack<C...>&&) -> framework::selected_pack<soa::is_self_index_t, C...> {}(columns_t{}));
template <typename IP>
using base_iterator = decltype(base_iter<D, O, IP>(columns_t{}));

template <typename IP, typename Parent, typename... T>
struct TableIteratorBase : base_iterator<IP> {
using columns_t = typename Parent::columns_t;
using external_index_columns_t = typename Parent::external_index_columns_t;
using bindings_pack_t = decltype([]<typename... C>(framework::pack<C...>) -> framework::pack<typename C::binding_t...> {}(external_index_columns_t{}));
using bindings_pack_t = typename base_iterator<IP>::bindings_pack_t;
// static constexpr const std::array<TableRef, sizeof...(T)> originals{T::ref...};
static constexpr auto originals = Parent::originals;
using policy_t = IP;
Expand Down Expand Up @@ -1828,7 +1869,7 @@ class Table
using decayed = std::decay_t<TI>;
if constexpr (framework::has_type<decayed>(bindings_pack_t{})) { // index to another table
constexpr auto idx = framework::has_type_at_v<decayed>(bindings_pack_t{});
return framework::pack_element_t<idx, external_index_columns_t>::getId();
return framework::pack_element_t<idx, columns_t>::getId();
} else if constexpr (std::same_as<decayed, Parent>) { // self index
return this->globalIndex();
} else if constexpr (is_indexing_column<decayed>) { // soa::Index<>
Expand All @@ -1838,20 +1879,17 @@ class Table
}
}

template <typename CD, typename... CDArgs>
template <soa::is_dynamic_column CD, typename... CDArgs>
auto getDynamicColumn() const
{
using decayed = std::decay_t<CD>;
static_assert(is_dynamic_t<decayed>(), "Requested column is not a dynamic column");
return static_cast<decayed>(*this).template getDynamicValue<CDArgs...>();
return static_cast<std::decay_t<CD>>(*this).template getDynamicValue<CDArgs...>();
}

template <typename B, typename CC>
requires(is_dynamic_column<CC> || is_persistent_column<CC>)
auto getValue() const
{
using COL = std::decay_t<CC>;
static_assert(is_dynamic_t<COL>() || soa::is_persistent_column<COL>, "Should be persistent or dynamic column with no argument that has a return type convertable to float");
return static_cast<B>(static_cast<COL>(*this).get());
return static_cast<B>(static_cast<std::decay_t<CC>>(*this).get());
}

template <typename B, typename... CCs>
Expand Down Expand Up @@ -2056,13 +2094,17 @@ class Table

void bindInternalIndicesExplicit(o2::soa::Binding binding)
{
doBindInternalIndicesExplicit(internal_index_columns_t{}, binding);
doBindInternalIndicesExplicit(columns_t{}, binding);
}

template <typename... Cs>
void doBindInternalIndicesExplicit(framework::pack<Cs...>, o2::soa::Binding binding)
{
(static_cast<Cs>(mBegin).setCurrentRaw(binding), ...);
(framework::overloaded{
[this, &binding]<is_self_index_column CI>() { static_cast<CI>(mBegin).setCurrentRaw(binding); },
[]<typename CI>() {}}
.template operator()<Cs>(),
...);
}

void bindExternalIndicesRaw(std::vector<o2::soa::Binding>&& ptrs)
Expand All @@ -2079,7 +2121,7 @@ class Table
template <typename T>
void copyIndexBindings(T& dest) const
{
doCopyIndexBindings(external_index_columns_t{}, dest);
doCopyIndexBindings(columns_t{}, dest);
}

auto select(framework::expressions::Filter const& f) const
Expand Down Expand Up @@ -3298,7 +3340,6 @@ class FilteredBase : public T
using T::originals;
using columns_t = typename T::columns_t;
using persistent_columns_t = typename T::persistent_columns_t;
using external_index_columns_t = typename T::external_index_columns_t;

using iterator = T::template iterator_template_o<FilteredIndexPolicy, self_t>;
using unfiltered_iterator = T::template iterator_template_o<DefaultIndexPolicy, self_t>;
Expand Down Expand Up @@ -3444,7 +3485,7 @@ class FilteredBase : public T
template <typename T1>
void copyIndexBindings(T1& dest) const
{
doCopyIndexBindings(external_index_columns_t{}, dest);
doCopyIndexBindings(columns_t{}, dest);
}

template <typename T1>
Expand Down
5 changes: 4 additions & 1 deletion Framework/Core/include/Framework/Configurable.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ struct Configurable : IP {
template <typename T, ConfigParamKind K = ConfigParamKind::kGeneric>
using MutableConfigurable = Configurable<T, K, ConfigurablePolicyMutable<T, K>>;

template <typename T>
concept is_configurable = requires(T& t) { &T::operator typename T::type; };

using ConfigurableAxis = Configurable<std::vector<double>, ConfigParamKind::kAxisSpec, ConfigurablePolicyConst<std::vector<double>, ConfigParamKind::kAxisSpec>>;

template <typename R, typename T, typename... As>
Expand All @@ -97,7 +100,7 @@ struct ProcessConfigurable : Configurable<bool, ConfigParamKind::kProcessFlag> {
};

template <typename T>
concept is_process_configurable = base_of_template<ProcessConfigurable, T>;
concept is_process_configurable = is_configurable<T> && requires(T& t) { t.process; };

#define PROCESS_SWITCH(_Class_, _Name_, _Help_, _Default_) \
decltype(ProcessConfigurable{&_Class_ ::_Name_, #_Name_, _Default_, _Help_}) do##_Name_ = ProcessConfigurable{&_Class_ ::_Name_, #_Name_, _Default_, _Help_};
Expand Down
22 changes: 19 additions & 3 deletions Framework/Core/include/Framework/GroupedCombinations.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,30 @@ auto interleaveTuples(std::tuple<T1s...>& t1, std::tuple<T2s...>& t2)
return interleaveTuplesImpl(t1, t2, std::index_sequence_for<T1s...>());
}

template <soa::is_index_column T, typename G>
requires(!soa::is_self_index_column<T>)
consteval auto isIndexTo()
{
if constexpr (o2::soa::is_binding_compatible_v<G, typename T::binding_t>()) {
return std::true_type{};
} else {
return std::false_type{};
}
}

template <typename T, typename G>
consteval auto isIndexTo()
{
return std::false_type{};
}

template <typename T, typename G>
using is_index_to_g_t = typename std::conditional<o2::soa::is_binding_compatible_v<G, typename T::binding_t>(), std::true_type, std::false_type>::type;
using is_index_to_g_t = decltype(isIndexTo<T, G>());

template <typename G, typename A>
expressions::BindingNode getMatchingIndexNode()
{
using external_index_columns_pack = typename A::external_index_columns_t;
using selected_indices_t = selected_pack_multicondition<is_index_to_g_t, pack<G>, external_index_columns_pack>;
using selected_indices_t = selected_pack_multicondition<is_index_to_g_t, pack<G>, typename A::columns_t>;
static_assert(pack_size(selected_indices_t{}) == 1, "No matching index column from associated to grouping");
using index_column_t = pack_head_t<selected_indices_t>;
return expressions::BindingNode{index_column_t::mLabel, o2::framework::TypeIdHelpers::uniqueId<typename index_column_t::column_t>(), expressions::selectArrowType<typename index_column_t::type>()};
Expand Down
Loading