Skip to content

Conversation

@leobeltra
Copy link

@leobeltra leobeltra commented Jul 24, 2025

PR description:

This PR extends the concept of SoA, introducing SoABlocks, i.e., a collection of SoA Layouts, with the corresponding Views and ConstViews. Both the memory abstraction and accessors to elements have been built by composition of multiple traditional SoAs. One of the purpose of SoABlocks is to substitute the role of PortableMultiCollection. For this reason, new constructors for PortableHostCollection and PortableDeviceCollection have been added.

The implementation of SoABlocks aims to mirror the design of the traditional SoALayout, so it has been written using macros. For a complete overview of the PR, the expanded code of the SoAGenericBlocksView_t.cc is taken as an example and attached to the description of this PR, in a separate comment (only SoAPCATemplate and SoAGenericBlocksTemplate, because SoAPosition is totally equivalent to SoAPCATemplate).

TODOs:

  • Provide a suitable method to print information about SoABlocks
  • Implement fully templated View and ConstView
  • Enable heterogeneous deepCopy() method for SoABlocks

PR validation:

For the validation four different tests have been added:

  • SoABlocks_t.cc tests the main properties of SoABlocks and its general utilization
  • SoAGenericBlocksView_t.cc can be seen as the extension of SoAGenericView_t.cc and tests the possibility to build the View or ConstView of an SoABlocks starting from Views or ConstViews of existing SoAs, and then deepCopy these Views in a contigous memory blob, that in this case is an SoABlocks instance
  • AssociationMapSoA.cc is a simple use case of the SoABlocks: an association map implemented using two SoA blocks where one gives the access to the other using SOA_VIEW_METHODS(...) and SOA_CONST_VIEW_METHODS(...) macros.
  • test_catch2_blocks.cc that tests the correct behaviour of SoABlocks instatiated using PortableHostCollection

FYI @felicepantaleo

@leobeltra
Copy link
Author

leobeltra commented Jul 24, 2025

template <std::size_t ALIGNMENT = cms::soa::CacheLineSize::defaultSize,
          bool ALIGNMENT_ENFORCEMENT = cms::soa::AlignmentEnforcement::relaxed>
struct SoAPCATemplate {
  using self_type = SoAPCATemplate;
  using AlignmentEnforcement = cms::soa::AlignmentEnforcement;
  using size_type = cms::soa::size_type;
  using byte_size_type = cms::soa::byte_size_type;
  constexpr static byte_size_type defaultAlignment = 128;
  constexpr static byte_size_type alignment = ALIGNMENT;
  constexpr static bool alignmentEnforcement = ALIGNMENT_ENFORCEMENT;
  constexpr static byte_size_type conditionalAlignment =
      alignmentEnforcement == cms::soa::AlignmentEnforcement::enforced ? alignment : 0;
  template <cms::soa::SoAColumnType COLUMN_TYPE, class C>
  using SoAValueWithConf = cms::soa::SoAValue<COLUMN_TYPE, C, conditionalAlignment>;
  template <cms::soa::SoAColumnType COLUMN_TYPE, class C>
  using SoAConstValueWithConf = cms::soa::SoAConstValue<COLUMN_TYPE, C, conditionalAlignment>;
  template <std::size_t VIEW_ALIGNMENT = cms::soa::CacheLineSize::defaultSize,
            bool VIEW_ALIGNMENT_ENFORCEMENT = cms::soa::AlignmentEnforcement::relaxed,
            bool RESTRICT_QUALIFY = cms::soa::RestrictQualify::Default,
            bool RANGE_CHECKING = cms::soa::RangeChecking::Default>
  struct ViewTemplateFreeParams;
  void soaToStreamInternal(std::ostream& _soa_impl_os) const {
    _soa_impl_os << "SoAPCATemplate"
                    "("
                 << elements_ << " elements, byte alignement= " << alignment << ", @" << mem_ << "): " << std::endl;
    _soa_impl_os << "  sizeof("
                    "SoAPCATemplate"
                    "): "
                 << sizeof(SoAPCATemplate) << std::endl;
    byte_size_type _soa_impl_offset = 0;
    _soa_impl_os << " Column "
                    "eigenvector_1"
                    " at offset "
                 << _soa_impl_offset << " has size " << sizeof(float) * elements_ << " and padding "
                 << cms::soa::alignSize(elements_ * sizeof(float), alignment) - (elements_ * sizeof(float))
                 << std::endl;
    _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(float), alignment);
    _soa_impl_os << " Column "
                    "eigenvector_2"
                    " at offset "
                 << _soa_impl_offset << " has size " << sizeof(float) * elements_ << " and padding "
                 << cms::soa::alignSize(elements_ * sizeof(float), alignment) - (elements_ * sizeof(float))
                 << std::endl;
    _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(float), alignment);
    _soa_impl_os << " Column "
                    "eigenvector_3"
                    " at offset "
                 << _soa_impl_offset << " has size " << sizeof(float) * elements_ << " and padding "
                 << cms::soa::alignSize(elements_ * sizeof(float), alignment) - (elements_ * sizeof(float))
                 << std::endl;
    _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(float), alignment);
    _soa_impl_os << " Eigen value "
                    "candidateDirection"
                    " at offset "
                 << _soa_impl_offset << " has dimension "
                 << "(" << Eigen::Vector3d::RowsAtCompileTime << " x " << Eigen::Vector3d::ColsAtCompileTime << ")"
                 << " and per column size " << sizeof(Eigen::Vector3d::Scalar) * elements_ << " and padding "
                 << cms::soa::alignSize(elements_ * sizeof(Eigen::Vector3d::Scalar), alignment) -
                        (elements_ * sizeof(Eigen::Vector3d::Scalar))
                 << std::endl;
    _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(Eigen::Vector3d::Scalar), alignment) *
                        Eigen::Vector3d::RowsAtCompileTime * Eigen::Vector3d::ColsAtCompileTime;
    _soa_impl_os << "Final offset = " << _soa_impl_offset << " computeDataSize(...): " << computeDataSize(elements_)
                 << std::endl;
    _soa_impl_os << std::endl;
  }
  static constexpr byte_size_type computeDataSize(size_type elements) {
    byte_size_type _soa_impl_ret = 0;
    _soa_impl_ret += cms::soa::alignSize(elements * sizeof(float), alignment);
    _soa_impl_ret += cms::soa::alignSize(elements * sizeof(float), alignment);
    _soa_impl_ret += cms::soa::alignSize(elements * sizeof(float), alignment);
    _soa_impl_ret += cms::soa::alignSize(elements * sizeof(Eigen::Vector3d::Scalar), alignment) *
                     Eigen::Vector3d::RowsAtCompileTime * Eigen::Vector3d::ColsAtCompileTime;
    return _soa_impl_ret;
  }
  struct Metadata {
    friend SoAPCATemplate;
    inline __attribute__((always_inline)) size_type size() const { return parent_.elements_; }
    inline __attribute__((always_inline)) byte_size_type byteSize() const { return parent_.byteSize_; }
    inline __attribute__((always_inline)) byte_size_type alignment() const { return SoAPCATemplate::alignment; }
    inline __attribute__((always_inline)) std::byte* data() { return parent_.mem_; }
    inline __attribute__((always_inline)) const std::byte* data() const { return parent_.mem_; }
    inline __attribute__((always_inline)) std::byte* nextByte() const { return parent_.mem_ + parent_.byteSize_; }
    inline __attribute__((always_inline)) SoAPCATemplate cloneToNewAddress(std::byte* _soa_impl_addr) const {
      return SoAPCATemplate(_soa_impl_addr, parent_.elements_);
    }
    using ParametersTypeOf_eigenvector_1 =
        cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::column>::DataType<float>;
    inline __attribute__((always_inline)) ParametersTypeOf_eigenvector_1 parametersOf_eigenvector_1() const {
      return ParametersTypeOf_eigenvector_1(parent_.eigenvector_1_);
    }
    inline __attribute__((always_inline)) float const* addressOf_eigenvector_1() const {
      return parent_.metadata().parametersOf_eigenvector_1().addr_;
    }
    inline __attribute__((always_inline)) float* addressOf_eigenvector_1() {
      return parent_.metadata().parametersOf_eigenvector_1().addr_;
    }
    inline __attribute__((always_inline)) byte_size_type eigenvector_1Pitch() const {
      return cms::soa::alignSize(parent_.elements_ * sizeof(float), ParentClass::alignment);
    }
    constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_1 = cms::soa::SoAColumnType::column;
    using ParametersTypeOf_eigenvector_2 =
        cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::column>::DataType<float>;
    inline __attribute__((always_inline)) ParametersTypeOf_eigenvector_2 parametersOf_eigenvector_2() const {
      return ParametersTypeOf_eigenvector_2(parent_.eigenvector_2_);
    }
    inline __attribute__((always_inline)) float const* addressOf_eigenvector_2() const {
      return parent_.metadata().parametersOf_eigenvector_2().addr_;
    }
    inline __attribute__((always_inline)) float* addressOf_eigenvector_2() {
      return parent_.metadata().parametersOf_eigenvector_2().addr_;
    }
    inline __attribute__((always_inline)) byte_size_type eigenvector_2Pitch() const {
      return cms::soa::alignSize(parent_.elements_ * sizeof(float), ParentClass::alignment);
    }
    constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_2 = cms::soa::SoAColumnType::column;
    using ParametersTypeOf_eigenvector_3 =
        cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::column>::DataType<float>;
    inline __attribute__((always_inline)) ParametersTypeOf_eigenvector_3 parametersOf_eigenvector_3() const {
      return ParametersTypeOf_eigenvector_3(parent_.eigenvector_3_);
    }
    inline __attribute__((always_inline)) float const* addressOf_eigenvector_3() const {
      return parent_.metadata().parametersOf_eigenvector_3().addr_;
    }
    inline __attribute__((always_inline)) float* addressOf_eigenvector_3() {
      return parent_.metadata().parametersOf_eigenvector_3().addr_;
    }
    inline __attribute__((always_inline)) byte_size_type eigenvector_3Pitch() const {
      return cms::soa::alignSize(parent_.elements_ * sizeof(float), ParentClass::alignment);
    }
    constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_3 = cms::soa::SoAColumnType::column;
    using ParametersTypeOf_candidateDirection =
        cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::eigen>::DataType<Eigen::Vector3d>;
    inline __attribute__((always_inline)) ParametersTypeOf_candidateDirection parametersOf_candidateDirection() const {
      return ParametersTypeOf_candidateDirection(parent_.candidateDirection_, parent_.candidateDirectionStride_);
    }
    inline __attribute__((always_inline)) byte_size_type candidateDirectionPitch() const {
      return cms::soa::alignSize(parent_.elements_ * sizeof(Eigen::Vector3d::Scalar), ParentClass::alignment) *
             Eigen::Vector3d::RowsAtCompileTime * Eigen::Vector3d::ColsAtCompileTime;
    }
    constexpr static cms::soa::SoAColumnType ColumnTypeOf_candidateDirection = cms::soa::SoAColumnType::eigen;
    inline __attribute__((always_inline)) Eigen::Vector3d::Scalar const* addressOf_candidateDirection() const {
      return parent_.metadata().parametersOf_candidateDirection().addr_;
    }
    inline __attribute__((always_inline)) Eigen::Vector3d::Scalar* addressOf_candidateDirection() {
      return parent_.metadata().parametersOf_candidateDirection().addr_;
    }
    struct value_element {
      inline __attribute__((always_inline)) value_element(float eigenvector_1,
                                                          float eigenvector_2,
                                                          float eigenvector_3,
                                                          Eigen::Vector3d candidateDirection)
          : eigenvector_1{eigenvector_1},
            eigenvector_2{eigenvector_2},
            eigenvector_3{eigenvector_3},
            candidateDirection{candidateDirection} {}
      float eigenvector_1;
      float eigenvector_2;
      float eigenvector_3;
      Eigen::Vector3d candidateDirection;
    };
    Metadata& operator=(const Metadata&) = delete;
    Metadata(const Metadata&) = delete;

  private:
    inline __attribute__((always_inline)) Metadata(const SoAPCATemplate& _soa_impl_parent)
        : parent_(_soa_impl_parent) {}
    const SoAPCATemplate& parent_;
    using ParentClass = SoAPCATemplate;
  };
  friend Metadata;
  inline __attribute__((always_inline)) const Metadata metadata() const { return Metadata(*this); }
  inline __attribute__((always_inline)) Metadata metadata() { return Metadata(*this); }
  template <std::size_t VIEW_ALIGNMENT, bool VIEW_ALIGNMENT_ENFORCEMENT, bool RESTRICT_QUALIFY, bool RANGE_CHECKING>
  struct ConstViewTemplateFreeParams {
    using self_type = ConstViewTemplateFreeParams;
    using SoAPCATemplate_parametrized = SoAPCATemplate<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT>;
    using size_type = cms::soa::size_type;
    using byte_size_type = cms::soa::byte_size_type;
    using AlignmentEnforcement = cms::soa::AlignmentEnforcement;
    template <std::size_t, bool, bool, bool>
    friend struct ViewTemplateFreeParams;
    template <std::size_t, bool, bool, bool>
    friend struct ConstViewTemplateFreeParams;
    constexpr static byte_size_type defaultAlignment = cms::soa::CacheLineSize::defaultSize;
    constexpr static byte_size_type alignment = VIEW_ALIGNMENT;
    constexpr static bool alignmentEnforcement = VIEW_ALIGNMENT_ENFORCEMENT;
    constexpr static byte_size_type conditionalAlignment =
        alignmentEnforcement == AlignmentEnforcement::enforced ? alignment : 0;
    constexpr static bool restrictQualify = RESTRICT_QUALIFY;
    constexpr static bool rangeChecking = RANGE_CHECKING;
    struct Metadata {
      friend ConstViewTemplateFreeParams;
      inline __attribute__((always_inline)) size_type size() const { return parent_.elements_; }
      using TypeOf_Layout = SoAPCATemplate_parametrized;
      using ParametersTypeOf_eigenvector_1 = typename TypeOf_Layout::Metadata::ParametersTypeOf_eigenvector_1;
      using TypeOf_eigenvector_1 = float;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_1 =
          TypeOf_Layout::Metadata::ColumnTypeOf_eigenvector_1;
      inline __attribute__((always_inline)) const auto parametersOf_eigenvector_1() const {
        return (parent_.eigenvector_1Parameters_);
      };
      using ParametersTypeOf_eigenvector_2 = typename TypeOf_Layout::Metadata::ParametersTypeOf_eigenvector_2;
      using TypeOf_eigenvector_2 = float;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_2 =
          TypeOf_Layout::Metadata::ColumnTypeOf_eigenvector_2;
      inline __attribute__((always_inline)) const auto parametersOf_eigenvector_2() const {
        return (parent_.eigenvector_2Parameters_);
      };
      using ParametersTypeOf_eigenvector_3 = typename TypeOf_Layout::Metadata::ParametersTypeOf_eigenvector_3;
      using TypeOf_eigenvector_3 = float;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_3 =
          TypeOf_Layout::Metadata::ColumnTypeOf_eigenvector_3;
      inline __attribute__((always_inline)) const auto parametersOf_eigenvector_3() const {
        return (parent_.eigenvector_3Parameters_);
      };
      using ParametersTypeOf_candidateDirection = typename TypeOf_Layout::Metadata::ParametersTypeOf_candidateDirection;
      using TypeOf_candidateDirection = Eigen::Vector3d;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_candidateDirection =
          TypeOf_Layout::Metadata::ColumnTypeOf_candidateDirection;
      inline __attribute__((always_inline)) const auto parametersOf_candidateDirection() const {
        return (parent_.candidateDirectionParameters_);
      };
      inline __attribute__((always_inline)) auto const* addressOf_eigenvector_1() const {
        return parent_.eigenvector_1Parameters_.addr_;
      };
      inline __attribute__((always_inline)) auto const* addressOf_eigenvector_2() const {
        return parent_.eigenvector_2Parameters_.addr_;
      };
      inline __attribute__((always_inline)) auto const* addressOf_eigenvector_3() const {
        return parent_.eigenvector_3Parameters_.addr_;
      };
      inline __attribute__((always_inline)) auto const* addressOf_candidateDirection() const {
        return parent_.candidateDirectionParameters_.addr_;
      };
      Metadata& operator=(const Metadata&) = delete;
      Metadata(const Metadata&) = delete;

    private:
      inline __attribute__((always_inline)) Metadata(const ConstViewTemplateFreeParams& _soa_impl_parent)
          : parent_(_soa_impl_parent) {}
      const ConstViewTemplateFreeParams& parent_;
    };
    friend Metadata;
    struct Metarecords {
      friend ConstViewTemplateFreeParams;
      Metarecords(const ConstViewTemplateFreeParams& _soa_impl_parent)
          : parent_(_soa_impl_parent),
            eigenvector_1_{parent_.metadata().parametersOf_eigenvector_1()},
            eigenvector_2_{parent_.metadata().parametersOf_eigenvector_2()},
            eigenvector_3_{parent_.metadata().parametersOf_eigenvector_3()},
            candidateDirection_{parent_.metadata().parametersOf_candidateDirection()} {}
      cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_eigenvector_1>::Type eigenvector_1() const {
        return std::make_tuple(eigenvector_1_, parent_.elements_);
      }
      cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_eigenvector_2>::Type eigenvector_2() const {
        return std::make_tuple(eigenvector_2_, parent_.elements_);
      }
      cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_eigenvector_3>::Type eigenvector_3() const {
        return std::make_tuple(eigenvector_3_, parent_.elements_);
      }
      cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_candidateDirection>::Type candidateDirection() const {
        return std::make_tuple(candidateDirection_, parent_.elements_);
      }

    private:
      const ConstViewTemplateFreeParams& parent_;
      typename Metadata::ParametersTypeOf_eigenvector_1::ConstType eigenvector_1_;
      typename Metadata::ParametersTypeOf_eigenvector_2::ConstType eigenvector_2_;
      typename Metadata::ParametersTypeOf_eigenvector_3::ConstType eigenvector_3_;
      typename Metadata::ParametersTypeOf_candidateDirection::ConstType candidateDirection_;
    };
    inline __attribute__((always_inline)) const Metadata metadata() const { return Metadata(*this); }
    inline __attribute__((always_inline)) const Metarecords records() const { return Metarecords(*this); }
    ConstViewTemplateFreeParams() = default;
    ConstViewTemplateFreeParams(const Metadata::TypeOf_Layout& layout)
        : elements_(layout.metadata().size()),
          eigenvector_1Parameters_([&]() -> auto {
            auto params = layout.metadata().parametersOf_eigenvector_1();
            if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
              if (reinterpret_cast<intptr_t>(params.addr_) % alignment)
                throw std::runtime_error(
                    "In constructor by layout: misaligned column: "
                    "eigenvector_1");
            return params;
          }()),
          eigenvector_2Parameters_([&]() -> auto {
            auto params = layout.metadata().parametersOf_eigenvector_2();
            if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
              if (reinterpret_cast<intptr_t>(params.addr_) % alignment)
                throw std::runtime_error(
                    "In constructor by layout: misaligned column: "
                    "eigenvector_2");
            return params;
          }()),
          eigenvector_3Parameters_([&]() -> auto {
            auto params = layout.metadata().parametersOf_eigenvector_3();
            if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
              if (reinterpret_cast<intptr_t>(params.addr_) % alignment)
                throw std::runtime_error(
                    "In constructor by layout: misaligned column: "
                    "eigenvector_3");
            return params;
          }()),
          candidateDirectionParameters_([&]() -> auto {
            auto params = layout.metadata().parametersOf_candidateDirection();
            if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
              if (reinterpret_cast<intptr_t>(params.addr_) % alignment)
                throw std::runtime_error(
                    "In constructor by layout: misaligned column: "
                    "candidateDirection");
            return params;
          }()) {}
    ConstViewTemplateFreeParams(
        cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_eigenvector_1>::Type eigenvector_1,
        cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_eigenvector_2>::Type eigenvector_2,
        cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_eigenvector_3>::Type eigenvector_3,
        cms::soa::ConstTuple<typename Metadata::ParametersTypeOf_candidateDirection>::Type candidateDirection) {
      bool readyToSet = false;
      if (not readyToSet) {
        elements_ = std::get<1>(eigenvector_1);
        readyToSet = true;
      }
      eigenvector_1Parameters_ = [&]() -> auto {
        if (elements_ != std::get<1>(eigenvector_1))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "eigenvector_1");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_eigenvector_1::checkAlignment(std::get<0>(eigenvector_1).tupleOrPointer(),
                                                                       alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "eigenvector_1");
        return std::get<0>(eigenvector_1);
      }();
      if (not readyToSet) {
        elements_ = std::get<1>(eigenvector_2);
        readyToSet = true;
      }
      eigenvector_2Parameters_ = [&]() -> auto {
        if (elements_ != std::get<1>(eigenvector_2))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "eigenvector_2");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_eigenvector_2::checkAlignment(std::get<0>(eigenvector_2).tupleOrPointer(),
                                                                       alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "eigenvector_2");
        return std::get<0>(eigenvector_2);
      }();
      if (not readyToSet) {
        elements_ = std::get<1>(eigenvector_3);
        readyToSet = true;
      }
      eigenvector_3Parameters_ = [&]() -> auto {
        if (elements_ != std::get<1>(eigenvector_3))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "eigenvector_3");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_eigenvector_3::checkAlignment(std::get<0>(eigenvector_3).tupleOrPointer(),
                                                                       alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "eigenvector_3");
        return std::get<0>(eigenvector_3);
      }();
      if (not readyToSet) {
        elements_ = std::get<1>(candidateDirection);
        readyToSet = true;
      }
      candidateDirectionParameters_ = [&]() -> auto {
        if (cms::soa::alignSize(elements_ * sizeof(Eigen::Vector3d::Scalar), alignment) /
                sizeof(Eigen::Vector3d::Scalar) !=
            std::get<0>(candidateDirection).stride_) {
          throw std::runtime_error(
              "In constructor by column pointers: stride not equal between eigen columns: "
              "candidateDirection");
        }
        if (elements_ != std::get<1>(candidateDirection))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "candidateDirection");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_candidateDirection::checkAlignment(
                  std::get<0>(candidateDirection).tupleOrPointer(), alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "candidateDirection");
        return std::get<0>(candidateDirection);
      }();
    }
    ConstViewTemplateFreeParams(ConstViewTemplateFreeParams const&) = default;
    ConstViewTemplateFreeParams& operator=(ConstViewTemplateFreeParams const&) = default;
    template <std::size_t OTHER_VIEW_ALIGNMENT,
              bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
              bool OTHER_RESTRICT_QUALIFY,
              bool OTHER_RANGE_CHECKING>
    ConstViewTemplateFreeParams(ConstViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT,
                                                            OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
                                                            OTHER_RESTRICT_QUALIFY,
                                                            OTHER_RANGE_CHECKING> const& other)
        : ConstViewTemplateFreeParams{
              other.elements_,
              cms::soa::const_cast_SoAParametersImpl(other.eigenvector_1Parameters_).tupleOrPointer(),
              cms::soa::const_cast_SoAParametersImpl(other.eigenvector_2Parameters_).tupleOrPointer(),
              cms::soa::const_cast_SoAParametersImpl(other.eigenvector_3Parameters_).tupleOrPointer(),
              cms::soa::const_cast_SoAParametersImpl(other.candidateDirectionParameters_).tupleOrPointer()} {}
    ConstViewTemplateFreeParams(size_type elems,
                                Metadata::ParametersTypeOf_eigenvector_1::ConstType eigenvector_1,
                                Metadata::ParametersTypeOf_eigenvector_2::ConstType eigenvector_2,
                                Metadata::ParametersTypeOf_eigenvector_3::ConstType eigenvector_3,
                                Metadata::ParametersTypeOf_candidateDirection::ConstType candidateDirection)
        : elements_{elems},
          eigenvector_1Parameters_{eigenvector_1},
          eigenvector_2Parameters_{eigenvector_2},
          eigenvector_3Parameters_{eigenvector_3},
          candidateDirectionParameters_{candidateDirection} {}
    template <std::size_t OTHER_VIEW_ALIGNMENT,
              bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
              bool OTHER_RESTRICT_QUALIFY,
              bool OTHER_RANGE_CHECKING>
    ConstViewTemplateFreeParams& operator=(ConstViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT,
                                                                       OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
                                                                       OTHER_RESTRICT_QUALIFY,
                                                                       OTHER_RANGE_CHECKING> const& other) {
      *this = other;
    }
    ConstViewTemplateFreeParams(ConstViewTemplateFreeParams&&) = default;
    ConstViewTemplateFreeParams& operator=(ConstViewTemplateFreeParams&&) = default;
    ~ConstViewTemplateFreeParams() = default;
    struct const_element {
      inline __attribute__((always_inline)) const_element(
          size_type _soa_impl_index,
          const typename Metadata::ParametersTypeOf_eigenvector_1::ConstType eigenvector_1,
          const typename Metadata::ParametersTypeOf_eigenvector_2::ConstType eigenvector_2,
          const typename Metadata::ParametersTypeOf_eigenvector_3::ConstType eigenvector_3,
          const typename Metadata::ParametersTypeOf_candidateDirection::ConstType candidateDirection)
          : eigenvector_1_(_soa_impl_index, eigenvector_1),
            eigenvector_2_(_soa_impl_index, eigenvector_2),
            eigenvector_3_(_soa_impl_index, eigenvector_3),
            candidateDirection_(_soa_impl_index, candidateDirection) {}
      inline __attribute__((always_inline)) const typename cms::soa::SoAConstValue_ColumnType<
          Metadata::ColumnTypeOf_eigenvector_1>::template DataType<typename Metadata::TypeOf_eigenvector_1>::
          template Alignment<conditionalAlignment>::template ConstValue<restrictQualify>::RefToConst
          eigenvector_1() const {
        return eigenvector_1_();
      }
      inline __attribute__((always_inline)) const typename cms::soa::SoAConstValue_ColumnType<
          Metadata::ColumnTypeOf_eigenvector_2>::template DataType<typename Metadata::TypeOf_eigenvector_2>::
          template Alignment<conditionalAlignment>::template ConstValue<restrictQualify>::RefToConst
          eigenvector_2() const {
        return eigenvector_2_();
      }
      inline __attribute__((always_inline)) const typename cms::soa::SoAConstValue_ColumnType<
          Metadata::ColumnTypeOf_eigenvector_3>::template DataType<typename Metadata::TypeOf_eigenvector_3>::
          template Alignment<conditionalAlignment>::template ConstValue<restrictQualify>::RefToConst
          eigenvector_3() const {
        return eigenvector_3_();
      }
      inline __attribute__((always_inline)) const typename cms::soa::SoAConstValue_ColumnType<
          Metadata::ColumnTypeOf_candidateDirection>::template DataType<typename Metadata::TypeOf_candidateDirection>::
          template Alignment<conditionalAlignment>::template ConstValue<restrictQualify>::RefToConst
          candidateDirection() const {
        return candidateDirection_();
      }

    private:
      const cms::soa::ConstValueTraitsFromC<
          typename cms::soa::SoAConstValue_ColumnType<Metadata::ColumnTypeOf_eigenvector_1>::template DataType<
              typename Metadata::TypeOf_eigenvector_1>::template Alignment<conditionalAlignment>::
              template ConstValue<restrictQualify>>
          eigenvector_1_;
      const cms::soa::ConstValueTraitsFromC<
          typename cms::soa::SoAConstValue_ColumnType<Metadata::ColumnTypeOf_eigenvector_2>::template DataType<
              typename Metadata::TypeOf_eigenvector_2>::template Alignment<conditionalAlignment>::
              template ConstValue<restrictQualify>>
          eigenvector_2_;
      const cms::soa::ConstValueTraitsFromC<
          typename cms::soa::SoAConstValue_ColumnType<Metadata::ColumnTypeOf_eigenvector_3>::template DataType<
              typename Metadata::TypeOf_eigenvector_3>::template Alignment<conditionalAlignment>::
              template ConstValue<restrictQualify>>
          eigenvector_3_;
      const cms::soa::ConstValueTraitsFromC<
          typename cms::soa::SoAConstValue_ColumnType<Metadata::ColumnTypeOf_candidateDirection>::template DataType<
              typename Metadata::TypeOf_candidateDirection>::template Alignment<conditionalAlignment>::
              template ConstValue<restrictQualify>>
          candidateDirection_;
    };
    inline __attribute__((always_inline)) const_element operator[](size_type _soa_impl_index) const {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in ConstViewTemplateFreeParams ::operator[]"),
                                              (_soa_impl_index),
                                              (elements_)));
        }
      }
      return const_element{_soa_impl_index,
                           eigenvector_1Parameters_,
                           eigenvector_2Parameters_,
                           eigenvector_3Parameters_,
                           candidateDirectionParameters_};
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        eigenvector_1() const {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              eigenvector_1Parameters_)();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        eigenvector_1(size_type _soa_impl_index) const {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in const "
                                               "eigenvector_1"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              eigenvector_1Parameters_)(_soa_impl_index);
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        eigenvector_2() const {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              eigenvector_2Parameters_)();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        eigenvector_2(size_type _soa_impl_index) const {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in const "
                                               "eigenvector_2"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              eigenvector_2Parameters_)(_soa_impl_index);
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        eigenvector_3() const {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              eigenvector_3Parameters_)();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        eigenvector_3(size_type _soa_impl_index) const {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in const "
                                               "eigenvector_3"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              eigenvector_3Parameters_)(_soa_impl_index);
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
        Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        candidateDirection() const {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
          Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              candidateDirectionParameters_)();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
        Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::constAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        candidateDirection(size_type _soa_impl_index) const {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in const "
                                               "candidateDirection"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
          Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::constAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              candidateDirectionParameters_)(_soa_impl_index);
    }
    template <typename T>
    friend void dump();

  private:
    size_type elements_ = 0;
    typename Metadata::ParametersTypeOf_eigenvector_1::ConstType eigenvector_1Parameters_;
    typename Metadata::ParametersTypeOf_eigenvector_2::ConstType eigenvector_2Parameters_;
    typename Metadata::ParametersTypeOf_eigenvector_3::ConstType eigenvector_3Parameters_;
    typename Metadata::ParametersTypeOf_candidateDirection::ConstType candidateDirectionParameters_;
  };
  template <bool RESTRICT_QUALIFY, bool RANGE_CHECKING>
  using ConstViewTemplate =
      ConstViewTemplateFreeParams<ALIGNMENT, ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY, RANGE_CHECKING>;
  using ConstView = ConstViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::Default>;
  template <std::size_t VIEW_ALIGNMENT, bool VIEW_ALIGNMENT_ENFORCEMENT, bool RESTRICT_QUALIFY, bool RANGE_CHECKING>
  struct ViewTemplateFreeParams
      : public ConstViewTemplateFreeParams<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY, RANGE_CHECKING> {
    using self_type = ViewTemplateFreeParams;
    using base_type =
        ConstViewTemplateFreeParams<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY, RANGE_CHECKING>;
    using SoAPCATemplate_parametrized = SoAPCATemplate<VIEW_ALIGNMENT, VIEW_ALIGNMENT_ENFORCEMENT>;
    using size_type = cms::soa::size_type;
    using byte_size_type = cms::soa::byte_size_type;
    using AlignmentEnforcement = cms::soa::AlignmentEnforcement;
    constexpr static byte_size_type defaultAlignment = cms::soa::CacheLineSize::defaultSize;
    constexpr static byte_size_type alignment = VIEW_ALIGNMENT;
    constexpr static bool alignmentEnforcement = VIEW_ALIGNMENT_ENFORCEMENT;
    constexpr static byte_size_type conditionalAlignment =
        alignmentEnforcement == AlignmentEnforcement::enforced ? alignment : 0;
    constexpr static bool restrictQualify = RESTRICT_QUALIFY;
    constexpr static bool rangeChecking = RANGE_CHECKING;
    template <std::size_t, bool, bool, bool>
    friend struct ViewTemplateFreeParams;
    struct Metadata {
      friend ViewTemplateFreeParams;
      inline __attribute__((always_inline)) size_type size() const { return parent_.elements_; }
      using TypeOf_Layout = SoAPCATemplate_parametrized;
      using ParametersTypeOf_eigenvector_1 = typename TypeOf_Layout::Metadata::ParametersTypeOf_eigenvector_1;
      using TypeOf_eigenvector_1 = float;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_1 =
          TypeOf_Layout::Metadata::ColumnTypeOf_eigenvector_1;
      inline __attribute__((always_inline)) const auto parametersOf_eigenvector_1() const {
        return cms::soa::const_cast_SoAParametersImpl(parent_.eigenvector_1Parameters_);
      };
      using ParametersTypeOf_eigenvector_2 = typename TypeOf_Layout::Metadata::ParametersTypeOf_eigenvector_2;
      using TypeOf_eigenvector_2 = float;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_2 =
          TypeOf_Layout::Metadata::ColumnTypeOf_eigenvector_2;
      inline __attribute__((always_inline)) const auto parametersOf_eigenvector_2() const {
        return cms::soa::const_cast_SoAParametersImpl(parent_.eigenvector_2Parameters_);
      };
      using ParametersTypeOf_eigenvector_3 = typename TypeOf_Layout::Metadata::ParametersTypeOf_eigenvector_3;
      using TypeOf_eigenvector_3 = float;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_eigenvector_3 =
          TypeOf_Layout::Metadata::ColumnTypeOf_eigenvector_3;
      inline __attribute__((always_inline)) const auto parametersOf_eigenvector_3() const {
        return cms::soa::const_cast_SoAParametersImpl(parent_.eigenvector_3Parameters_);
      };
      using ParametersTypeOf_candidateDirection = typename TypeOf_Layout::Metadata::ParametersTypeOf_candidateDirection;
      using TypeOf_candidateDirection = Eigen::Vector3d;
      constexpr static cms::soa::SoAColumnType ColumnTypeOf_candidateDirection =
          TypeOf_Layout::Metadata::ColumnTypeOf_candidateDirection;
      inline __attribute__((always_inline)) const auto parametersOf_candidateDirection() const {
        return cms::soa::const_cast_SoAParametersImpl(parent_.candidateDirectionParameters_);
      };
      inline __attribute__((always_inline)) auto* addressOf_eigenvector_1() {
        return parametersOf_eigenvector_1().addr_;
      };
      inline __attribute__((always_inline)) auto* addressOf_eigenvector_2() {
        return parametersOf_eigenvector_2().addr_;
      };
      inline __attribute__((always_inline)) auto* addressOf_eigenvector_3() {
        return parametersOf_eigenvector_3().addr_;
      };
      inline __attribute__((always_inline)) auto* addressOf_candidateDirection() {
        return parametersOf_candidateDirection().addr_;
      };
      inline __attribute__((always_inline)) auto const* addressOf_eigenvector_1() const {
        return parent_.eigenvector_1Parameters_.addr_;
      };
      inline __attribute__((always_inline)) auto const* addressOf_eigenvector_2() const {
        return parent_.eigenvector_2Parameters_.addr_;
      };
      inline __attribute__((always_inline)) auto const* addressOf_eigenvector_3() const {
        return parent_.eigenvector_3Parameters_.addr_;
      };
      inline __attribute__((always_inline)) auto const* addressOf_candidateDirection() const {
        return parent_.candidateDirectionParameters_.addr_;
      };
      Metadata& operator=(const Metadata&) = delete;
      Metadata(const Metadata&) = delete;

    private:
      inline __attribute__((always_inline)) Metadata(const ViewTemplateFreeParams& _soa_impl_parent)
          : parent_(_soa_impl_parent) {}
      const ViewTemplateFreeParams& parent_;
    };
    friend Metadata;
    struct Metarecords {
      friend ViewTemplateFreeParams;
      Metarecords(const ViewTemplateFreeParams& _soa_impl_parent)
          : parent_(_soa_impl_parent),
            eigenvector_1_{parent_.metadata().parametersOf_eigenvector_1()},
            eigenvector_2_{parent_.metadata().parametersOf_eigenvector_2()},
            eigenvector_3_{parent_.metadata().parametersOf_eigenvector_3()},
            candidateDirection_{parent_.metadata().parametersOf_candidateDirection()} {}
      cms::soa::Tuple<typename Metadata::ParametersTypeOf_eigenvector_1>::Type eigenvector_1() const {
        return std::make_tuple(eigenvector_1_, parent_.elements_);
      }
      cms::soa::Tuple<typename Metadata::ParametersTypeOf_eigenvector_2>::Type eigenvector_2() const {
        return std::make_tuple(eigenvector_2_, parent_.elements_);
      }
      cms::soa::Tuple<typename Metadata::ParametersTypeOf_eigenvector_3>::Type eigenvector_3() const {
        return std::make_tuple(eigenvector_3_, parent_.elements_);
      }
      cms::soa::Tuple<typename Metadata::ParametersTypeOf_candidateDirection>::Type candidateDirection() const {
        return std::make_tuple(candidateDirection_, parent_.elements_);
      }

    private:
      const ViewTemplateFreeParams& parent_;
      typename Metadata::ParametersTypeOf_eigenvector_1 eigenvector_1_;
      typename Metadata::ParametersTypeOf_eigenvector_2 eigenvector_2_;
      typename Metadata::ParametersTypeOf_eigenvector_3 eigenvector_3_;
      typename Metadata::ParametersTypeOf_candidateDirection candidateDirection_;
    };
    inline __attribute__((always_inline)) const Metadata metadata() const { return Metadata(*this); }
    inline __attribute__((always_inline)) Metadata metadata() { return Metadata(*this); }
    inline __attribute__((always_inline)) const Metarecords records() const { return Metarecords(*this); }
    inline __attribute__((always_inline)) Metarecords records() { return Metarecords(*this); }
    ViewTemplateFreeParams() = default;
    ViewTemplateFreeParams(const Metadata::TypeOf_Layout& layout) : base_type{layout} {}
    ViewTemplateFreeParams(
        cms::soa::Tuple<typename Metadata::ParametersTypeOf_eigenvector_1>::Type eigenvector_1,
        cms::soa::Tuple<typename Metadata::ParametersTypeOf_eigenvector_2>::Type eigenvector_2,
        cms::soa::Tuple<typename Metadata::ParametersTypeOf_eigenvector_3>::Type eigenvector_3,
        cms::soa::Tuple<typename Metadata::ParametersTypeOf_candidateDirection>::Type candidateDirection) {
      bool readyToSet = false;
      if (not readyToSet) {
        base_type::elements_ = std::get<1>(eigenvector_1);
        readyToSet = true;
      }
      base_type::eigenvector_1Parameters_ = [&]() -> auto {
        if (base_type::elements_ != std::get<1>(eigenvector_1))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "eigenvector_1");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_eigenvector_1::checkAlignment(std::get<0>(eigenvector_1).tupleOrPointer(),
                                                                       alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "eigenvector_1");
        return std::get<0>(eigenvector_1);
      }();
      if (not readyToSet) {
        base_type::elements_ = std::get<1>(eigenvector_2);
        readyToSet = true;
      }
      base_type::eigenvector_2Parameters_ = [&]() -> auto {
        if (base_type::elements_ != std::get<1>(eigenvector_2))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "eigenvector_2");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_eigenvector_2::checkAlignment(std::get<0>(eigenvector_2).tupleOrPointer(),
                                                                       alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "eigenvector_2");
        return std::get<0>(eigenvector_2);
      }();
      if (not readyToSet) {
        base_type::elements_ = std::get<1>(eigenvector_3);
        readyToSet = true;
      }
      base_type::eigenvector_3Parameters_ = [&]() -> auto {
        if (base_type::elements_ != std::get<1>(eigenvector_3))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "eigenvector_3");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_eigenvector_3::checkAlignment(std::get<0>(eigenvector_3).tupleOrPointer(),
                                                                       alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "eigenvector_3");
        return std::get<0>(eigenvector_3);
      }();
      if (not readyToSet) {
        base_type::elements_ = std::get<1>(candidateDirection);
        readyToSet = true;
      }
      base_type::candidateDirectionParameters_ = [&]() -> auto {
        if (cms::soa::alignSize(base_type::elements_ * sizeof(Eigen::Vector3d::Scalar), alignment) /
                sizeof(Eigen::Vector3d::Scalar) !=
            std::get<0>(candidateDirection).stride_) {
          throw std::runtime_error(
              "In constructor by column pointers: stride not equal between eigen columns: "
              "candidateDirection");
        }
        if (base_type::elements_ != std::get<1>(candidateDirection))
          throw std::runtime_error(
              "In constructor by column pointers: number of elements not equal for every column: "
              "candidateDirection");
        if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
          if (Metadata::ParametersTypeOf_candidateDirection::checkAlignment(
                  std::get<0>(candidateDirection).tupleOrPointer(), alignment))
            throw std::runtime_error(
                "In constructor by column: misaligned column: "
                "candidateDirection");
        return std::get<0>(candidateDirection);
      }();
    }
    ViewTemplateFreeParams(size_type elems,
                           Metadata::ParametersTypeOf_eigenvector_1 eigenvector_1,
                           Metadata::ParametersTypeOf_eigenvector_2 eigenvector_2,
                           Metadata::ParametersTypeOf_eigenvector_3 eigenvector_3,
                           Metadata::ParametersTypeOf_candidateDirection candidateDirection)
        : base_type{elems, eigenvector_1, eigenvector_2, eigenvector_3, candidateDirection} {}
    ViewTemplateFreeParams(ViewTemplateFreeParams const&) = default;
    ViewTemplateFreeParams& operator=(ViewTemplateFreeParams const&) = default;
    template <std::size_t OTHER_VIEW_ALIGNMENT,
              bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
              bool OTHER_RESTRICT_QUALIFY,
              bool OTHER_RANGE_CHECKING>
    ViewTemplateFreeParams(ViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT,
                                                  OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
                                                  OTHER_RESTRICT_QUALIFY,
                                                  OTHER_RANGE_CHECKING> const& other)
        : base_type{other.elements_,
                    cms::soa::const_cast_SoAParametersImpl(other.eigenvector_1Parameters_).tupleOrPointer(),
                    cms::soa::const_cast_SoAParametersImpl(other.eigenvector_2Parameters_).tupleOrPointer(),
                    cms::soa::const_cast_SoAParametersImpl(other.eigenvector_3Parameters_).tupleOrPointer(),
                    cms::soa::const_cast_SoAParametersImpl(other.candidateDirectionParameters_).tupleOrPointer()} {}
    template <std::size_t OTHER_VIEW_ALIGNMENT,
              bool OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
              bool OTHER_RESTRICT_QUALIFY,
              bool OTHER_RANGE_CHECKING>
    ViewTemplateFreeParams& operator=(ViewTemplateFreeParams<OTHER_VIEW_ALIGNMENT,
                                                             OTHER_VIEW_ALIGNMENT_ENFORCEMENT,
                                                             OTHER_RESTRICT_QUALIFY,
                                                             OTHER_RANGE_CHECKING> const& other) {
      static_cast<base_type>(*this) = static_cast<base_type>(other);
    }
    ViewTemplateFreeParams(ViewTemplateFreeParams&&) = default;
    ViewTemplateFreeParams& operator=(ViewTemplateFreeParams&&) = default;
    ~ViewTemplateFreeParams() = default;
    using const_element = typename base_type::const_element;
    using base_type::operator[];
    struct element {
      inline __attribute__((always_inline)) element(
          size_type _soa_impl_index,
          typename Metadata::ParametersTypeOf_eigenvector_1 eigenvector_1,
          typename Metadata::ParametersTypeOf_eigenvector_2 eigenvector_2,
          typename Metadata::ParametersTypeOf_eigenvector_3 eigenvector_3,
          typename Metadata::ParametersTypeOf_candidateDirection candidateDirection)
          : eigenvector_1(_soa_impl_index, eigenvector_1),
            eigenvector_2(_soa_impl_index, eigenvector_2),
            eigenvector_3(_soa_impl_index, eigenvector_3),
            candidateDirection(_soa_impl_index, candidateDirection) {}
      inline __attribute__((always_inline)) element& operator=(const element& _soa_impl_other) {
        if constexpr (Metadata::ColumnTypeOf_eigenvector_1 != cms::soa::SoAColumnType::scalar) {
          eigenvector_1() = _soa_impl_other.eigenvector_1();
        }
        if constexpr (Metadata::ColumnTypeOf_eigenvector_2 != cms::soa::SoAColumnType::scalar) {
          eigenvector_2() = _soa_impl_other.eigenvector_2();
        }
        if constexpr (Metadata::ColumnTypeOf_eigenvector_3 != cms::soa::SoAColumnType::scalar) {
          eigenvector_3() = _soa_impl_other.eigenvector_3();
        }
        if constexpr (Metadata::ColumnTypeOf_candidateDirection != cms::soa::SoAColumnType::scalar) {
          candidateDirection() = _soa_impl_other.candidateDirection();
        }
        return *this;
      }
      inline __attribute__((always_inline)) element& operator=(const const_element& _soa_impl_other) {
        if constexpr (Metadata::ColumnTypeOf_eigenvector_1 != cms::soa::SoAColumnType::scalar) {
          eigenvector_1() = _soa_impl_other.eigenvector_1();
        }
        if constexpr (Metadata::ColumnTypeOf_eigenvector_2 != cms::soa::SoAColumnType::scalar) {
          eigenvector_2() = _soa_impl_other.eigenvector_2();
        }
        if constexpr (Metadata::ColumnTypeOf_eigenvector_3 != cms::soa::SoAColumnType::scalar) {
          eigenvector_3() = _soa_impl_other.eigenvector_3();
        }
        if constexpr (Metadata::ColumnTypeOf_candidateDirection != cms::soa::SoAColumnType::scalar) {
          candidateDirection() = _soa_impl_other.candidateDirection();
        }
        return *this;
      }
      inline __attribute__((always_inline)) constexpr element& operator=(
          const typename SoAPCATemplate_parametrized::Metadata::value_element _soa_impl_value) {
        eigenvector_1() = _soa_impl_value.eigenvector_1;
        eigenvector_2() = _soa_impl_value.eigenvector_2;
        eigenvector_3() = _soa_impl_value.eigenvector_3;
        candidateDirection() = _soa_impl_value.candidateDirection;
        return *this;
      }
      typename cms::soa::SoAValue_ColumnType<Metadata::ColumnTypeOf_eigenvector_1>::template DataType<
          typename Metadata::TypeOf_eigenvector_1>::template Alignment<conditionalAlignment>::
          template Value<restrictQualify>
              eigenvector_1;
      typename cms::soa::SoAValue_ColumnType<Metadata::ColumnTypeOf_eigenvector_2>::template DataType<
          typename Metadata::TypeOf_eigenvector_2>::template Alignment<conditionalAlignment>::
          template Value<restrictQualify>
              eigenvector_2;
      typename cms::soa::SoAValue_ColumnType<Metadata::ColumnTypeOf_eigenvector_3>::template DataType<
          typename Metadata::TypeOf_eigenvector_3>::template Alignment<conditionalAlignment>::
          template Value<restrictQualify>
              eigenvector_3;
      typename cms::soa::SoAValue_ColumnType<Metadata::ColumnTypeOf_candidateDirection>::template DataType<
          typename Metadata::TypeOf_candidateDirection>::template Alignment<conditionalAlignment>::
          template Value<restrictQualify>
              candidateDirection;
    };
    inline __attribute__((always_inline)) element operator[](size_type _soa_impl_index) {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= base_type::elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in ViewTemplateFreeParams ::operator[]"),
                                              (_soa_impl_index),
                                              (base_type::elements_)));
        }
      }
      return element{_soa_impl_index,
                     cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_1Parameters_),
                     cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_2Parameters_),
                     cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_3Parameters_),
                     cms::soa::const_cast_SoAParametersImpl(base_type::candidateDirectionParameters_)};
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        eigenvector_1() {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_1Parameters_))();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        eigenvector_1(size_type _soa_impl_index) {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= base_type::elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in mutable "
                                               "eigenvector_1"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (base_type::elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_1>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_1>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_1Parameters_))(_soa_impl_index);
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        eigenvector_2() {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_2Parameters_))();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        eigenvector_2(size_type _soa_impl_index) {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= base_type::elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in mutable "
                                               "eigenvector_2"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (base_type::elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_2>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_2>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_2Parameters_))(_soa_impl_index);
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        eigenvector_3() {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_3Parameters_))();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
        Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        eigenvector_3(size_type _soa_impl_index) {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= base_type::elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in mutable "
                                               "eigenvector_3"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (base_type::elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_eigenvector_3>::template ColumnType<
          Metadata::ColumnTypeOf_eigenvector_3>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::eigenvector_3Parameters_))(_soa_impl_index);
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
        Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::NoParamReturnType
        candidateDirection() {
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
          Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::candidateDirectionParameters_))();
    }
    inline __attribute__((always_inline))
    typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
        Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
        template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>::ParamReturnType
        candidateDirection(size_type _soa_impl_index) {
      if constexpr (rangeChecking == cms::soa::RangeChecking::enabled) {
        if (_soa_impl_index >= base_type::elements_ or _soa_impl_index < 0) {
          throw std::out_of_range(fmt::format("{}: index {} out of range {}",
                                              ("Out of range index in mutable "
                                               "candidateDirection"
                                               "(size_type index)"),
                                              (_soa_impl_index),
                                              (base_type::elements_)));
        }
      }
      return typename cms::soa::SoAAccessors<typename Metadata::TypeOf_candidateDirection>::template ColumnType<
          Metadata::ColumnTypeOf_candidateDirection>::template AccessType<cms::soa::SoAAccessType::mutableAccess>::
          template Alignment<conditionalAlignment>::template RestrictQualifier<restrictQualify>(
              cms::soa::const_cast_SoAParametersImpl(base_type::candidateDirectionParameters_))(_soa_impl_index);
    }
    template <typename T>
    friend void dump();
  };
  template <bool RESTRICT_QUALIFY, bool RANGE_CHECKING>
  using ViewTemplate = ViewTemplateFreeParams<ALIGNMENT, ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY, RANGE_CHECKING>;
  using View = ViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::Default>;
  struct ConstDescriptor {
    ConstDescriptor() = default;
    explicit ConstDescriptor(ConstView const& view)
        : buff{std::span(view.metadata().addressOf_eigenvector_1(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(float), alignment) / sizeof(float)),
               std::span(view.metadata().addressOf_eigenvector_2(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(float), alignment) / sizeof(float)),
               std::span(view.metadata().addressOf_eigenvector_3(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(float), alignment) / sizeof(float)),
               std::span(view.metadata().addressOf_candidateDirection(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(Eigen::Vector3d::Scalar), alignment) *
                             Eigen::Vector3d::RowsAtCompileTime * Eigen::Vector3d::ColsAtCompileTime /
                             sizeof(Eigen::Vector3d::Scalar))} {}
    std::tuple<std::span<std::add_const_t<float>>,
               std::span<std::add_const_t<float>>,
               std::span<std::add_const_t<float>>,
               std::span<std::add_const_t<Eigen::Vector3d::Scalar>>>
        buff;
    static constexpr size_type num_cols =
        std::tuple_size<std::tuple<std::span<std::add_const_t<float>>,
                                   std::span<std::add_const_t<float>>,
                                   std::span<std::add_const_t<float>>,
                                   std::span<std::add_const_t<Eigen::Vector3d::Scalar>>>>::value;
  };
  struct Descriptor {
    Descriptor() = default;
    explicit Descriptor(View& view)
        : buff{std::span(view.metadata().addressOf_eigenvector_1(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(float), alignment) / sizeof(float)),
               std::span(view.metadata().addressOf_eigenvector_2(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(float), alignment) / sizeof(float)),
               std::span(view.metadata().addressOf_eigenvector_3(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(float), alignment) / sizeof(float)),
               std::span(view.metadata().addressOf_candidateDirection(),
                         cms::soa::alignSize(view.metadata().size() * sizeof(Eigen::Vector3d::Scalar), alignment) *
                             Eigen::Vector3d::RowsAtCompileTime * Eigen::Vector3d::ColsAtCompileTime /
                             sizeof(Eigen::Vector3d::Scalar))} {}
    std::tuple<std::span<float>, std::span<float>, std::span<float>, std::span<Eigen::Vector3d::Scalar>> buff;
    static constexpr size_type num_cols = std::tuple_size<
        std::tuple<std::span<float>, std::span<float>, std::span<float>, std::span<Eigen::Vector3d::Scalar>>>::value;
  };
  SoAPCATemplate()
      : mem_(nullptr),
        elements_(0),
        byteSize_(0),
        eigenvector_1_(nullptr),
        eigenvector_2_(nullptr),
        eigenvector_3_(nullptr),
        candidateDirectionElementsWithPadding_(0),
        candidateDirection_(nullptr),
        candidateDirectionStride_(0) {}
  SoAPCATemplate(std::byte* mem, size_type elements) : mem_(mem), elements_(elements), byteSize_(0) {
    organizeColumnsFromBuffer();
  }
  SoAPCATemplate(SoAPCATemplate const& _soa_impl_other)
      : mem_(_soa_impl_other.mem_),
        elements_(_soa_impl_other.elements_),
        byteSize_(_soa_impl_other.byteSize_),
        eigenvector_1_{_soa_impl_other.eigenvector_1_},
        eigenvector_2_{_soa_impl_other.eigenvector_2_},
        eigenvector_3_{_soa_impl_other.eigenvector_3_},
        candidateDirectionElementsWithPadding_{_soa_impl_other.candidateDirectionElementsWithPadding_},
        candidateDirection_{_soa_impl_other.candidateDirection_},
        candidateDirectionStride_{_soa_impl_other.candidateDirectionStride_} {}
  SoAPCATemplate& operator=(SoAPCATemplate const& _soa_impl_other) {
    mem_ = _soa_impl_other.mem_;
    elements_ = _soa_impl_other.elements_;
    byteSize_ = _soa_impl_other.byteSize_;
    eigenvector_1_ = _soa_impl_other.eigenvector_1_;
    eigenvector_2_ = _soa_impl_other.eigenvector_2_;
    eigenvector_3_ = _soa_impl_other.eigenvector_3_;
    candidateDirectionElementsWithPadding_ = _soa_impl_other.candidateDirectionElementsWithPadding_;
    candidateDirection_ = _soa_impl_other.candidateDirection_;
    candidateDirectionStride_ = _soa_impl_other.candidateDirectionStride_;
    return *this;
  }
  inline __attribute__((always_inline)) static View const_cast_View(ConstView const& view) {
    return View{view.metadata().size(),
                cms::soa::const_cast_SoAParametersImpl(view.metadata().parametersOf_eigenvector_1()),
                cms::soa::const_cast_SoAParametersImpl(view.metadata().parametersOf_eigenvector_2()),
                cms::soa::const_cast_SoAParametersImpl(view.metadata().parametersOf_eigenvector_3()),
                cms::soa::const_cast_SoAParametersImpl(view.metadata().parametersOf_candidateDirection())};
  }
  void deepCopy(ConstView const& view) {
    if (elements_ < view.metadata().size())
      throw std::runtime_error(
          "In "
          "SoAPCATemplate"
          "::deepCopy method: number of elements mismatch ");
    memcpy(this->metadata().addressOf_eigenvector_1(),
           view.metadata().addressOf_eigenvector_1(),
           view.metadata().size() * sizeof(float));
    memcpy(this->metadata().addressOf_eigenvector_2(),
           view.metadata().addressOf_eigenvector_2(),
           view.metadata().size() * sizeof(float));
    memcpy(this->metadata().addressOf_eigenvector_3(),
           view.metadata().addressOf_eigenvector_3(),
           view.metadata().size() * sizeof(float));
    memcpy(this->metadata().addressOf_candidateDirection(),
           view.metadata().addressOf_candidateDirection(),
           candidateDirectionElementsWithPadding_ * sizeof(Eigen::Vector3d::Scalar));
  }
  template <typename T>
  void ROOTReadStreamer(T& onfile) {
    memcpy(eigenvector_1_, onfile.eigenvector_1_, sizeof(float) * onfile.elements_);
    memcpy(eigenvector_2_, onfile.eigenvector_2_, sizeof(float) * onfile.elements_);
    memcpy(eigenvector_3_, onfile.eigenvector_3_, sizeof(float) * onfile.elements_);
    memcpy(candidateDirection_,
           onfile.candidateDirection_,
           sizeof(Eigen::Vector3d::Scalar) * candidateDirectionElementsWithPadding_);
  }
  void ROOTStreamerCleaner() {
    delete[] eigenvector_1_;
    eigenvector_1_ = nullptr;
    delete[] eigenvector_2_;
    eigenvector_2_ = nullptr;
    delete[] eigenvector_3_;
    eigenvector_3_ = nullptr;
    delete[] candidateDirection_;
    candidateDirection_ = nullptr;
  }
  template <typename T>
  friend void dump();

private:
  void organizeColumnsFromBuffer() {
    if constexpr (alignmentEnforcement == cms::soa::AlignmentEnforcement::enforced)
      if (reinterpret_cast<intptr_t>(mem_) % alignment)
        throw std::runtime_error(
            "In "
            "SoAPCATemplate"
            "::"
            "SoAPCATemplate"
            ": misaligned buffer");
    auto _soa_impl_curMem = mem_;
    eigenvector_1_ = reinterpret_cast<float*>(_soa_impl_curMem);
    _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(float), alignment);
    if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
      if (reinterpret_cast<intptr_t>(eigenvector_1_) % alignment)
        throw std::runtime_error(
            "In layout constructor: misaligned column: "
            "eigenvector_1");
    eigenvector_2_ = reinterpret_cast<float*>(_soa_impl_curMem);
    _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(float), alignment);
    if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
      if (reinterpret_cast<intptr_t>(eigenvector_2_) % alignment)
        throw std::runtime_error(
            "In layout constructor: misaligned column: "
            "eigenvector_2");
    eigenvector_3_ = reinterpret_cast<float*>(_soa_impl_curMem);
    _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(float), alignment);
    if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
      if (reinterpret_cast<intptr_t>(eigenvector_3_) % alignment)
        throw std::runtime_error(
            "In layout constructor: misaligned column: "
            "eigenvector_3");
    candidateDirectionStride_ =
        cms::soa::alignSize(elements_ * sizeof(Eigen::Vector3d::Scalar), alignment) / sizeof(Eigen::Vector3d::Scalar);
    candidateDirectionElementsWithPadding_ =
        candidateDirectionStride_ * Eigen::Vector3d::RowsAtCompileTime * Eigen::Vector3d::ColsAtCompileTime;
    candidateDirection_ = reinterpret_cast<Eigen::Vector3d::Scalar*>(_soa_impl_curMem);
    _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(Eigen::Vector3d::Scalar), alignment) *
                        Eigen::Vector3d::RowsAtCompileTime * Eigen::Vector3d::ColsAtCompileTime;
    if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)
      if (reinterpret_cast<intptr_t>(candidateDirection_) % alignment)
        throw std::runtime_error(
            "In layout constructor: misaligned column: "
            "candidateDirection");
    byteSize_ = computeDataSize(elements_);
    if (mem_ + byteSize_ != _soa_impl_curMem)
      throw std::runtime_error(
          "In "
          "SoAPCATemplate"
          "::"
          "SoAPCATemplate"
          ": unexpected end pointer.");
  }
  static constexpr std::pair<size_type, size_type> computeMethodsNumber() {
    size_type _soa_methods_count = 0;
    size_type _soa_const_methods_count = 0;
    return {_soa_methods_count, _soa_const_methods_count};
  }
  static_assert(computeMethodsNumber().first <= 1,
                "There can be at most one SOA_ELEMENT_METHODS macro."
                "Please declare all your methods inside the same macro.");
  static_assert(computeMethodsNumber().second <= 1,
                "There can be at most one SOA_CONST_ELEMENT_METHODS macro."
                "Please declare all your methods inside the same macro.");
  std::byte* mem_;
  size_type elements_;
  size_type const scalar_ = 1;
  byte_size_type byteSize_;
  float* eigenvector_1_ = nullptr;
  float* eigenvector_2_ = nullptr;
  float* eigenvector_3_ = nullptr;
  size_type candidateDirectionElementsWithPadding_ = 0;
  Eigen::Vector3d::Scalar* candidateDirection_ = nullptr;
  byte_size_type candidateDirectionStride_ = 0;
};
using SoAPCA = SoAPCATemplate<>;
using SoAPCAView = SoAPCA::View;
using SoAPCAConstView = SoAPCA::ConstView;
template <std::size_t ALIGNMENT = cms::soa::CacheLineSize::defaultSize,
          bool ALIGNMENT_ENFORCEMENT = cms::soa::AlignmentEnforcement::relaxed>
struct SoAGenericBlocksTemplate {
  using size_type = cms::soa::size_type;
  using byte_size_type = cms::soa::byte_size_type;
  constexpr static byte_size_type alignment = ALIGNMENT;
  struct ConstView;
  struct View;
  static constexpr size_type computeBlocksNumber() {
    size_type soa_blocks_count = 0;
    soa_blocks_count += 1;
    soa_blocks_count += 1;
    return soa_blocks_count;
  }
  static constexpr size_type blocksNumber = computeBlocksNumber();
  static constexpr byte_size_type computeDataSize(std::array<size_type, blocksNumber> sizes) {
    byte_size_type _soa_impl_ret = 0;
    size_type index = 0;
    _soa_impl_ret += SoAPositionTemplate<ALIGNMENT>::computeDataSize(sizes[index]);
    index++;
    _soa_impl_ret += SoAPCATemplate<ALIGNMENT>::computeDataSize(sizes[index]);
    index++;
    return _soa_impl_ret;
  }
  struct Metadata {
    friend SoAGenericBlocksTemplate;
    inline __attribute__((always_inline)) std::array<size_type, blocksNumber> size() const { return parent_.sizes_; }
    inline __attribute__((always_inline)) byte_size_type byteSize() const {
      return SoAGenericBlocksTemplate::computeDataSize(parent_.size_);
    }
    inline __attribute__((always_inline)) byte_size_type alignment() const {
      return SoAGenericBlocksTemplate::alignment;
    }
    inline __attribute__((always_inline)) SoAGenericBlocksTemplate cloneToNewAddress(std::byte* _soa_impl_addr) const {
      return SoAGenericBlocksTemplate(_soa_impl_addr, parent_.sizes_);
    }
    inline __attribute__((always_inline)) auto const* addressOf_position() const {
      return parent_.position_.metadata().data();
    }
    inline __attribute__((always_inline)) auto* addressOf_position() { return parent_.position_.metadata().data(); }
    inline __attribute__((always_inline)) auto const* addressOf_pca() const { return parent_.pca_.metadata().data(); }
    inline __attribute__((always_inline)) auto* addressOf_pca() { return parent_.pca_.metadata().data(); }
    Metadata& operator=(const Metadata&) = delete;
    Metadata(const Metadata&) = delete;

  private:
    inline __attribute__((always_inline)) Metadata(const SoAGenericBlocksTemplate& _soa_impl_parent)
        : parent_(_soa_impl_parent) {}
    const SoAGenericBlocksTemplate& parent_;
  };
  friend Metadata;
  inline __attribute__((always_inline)) const Metadata metadata() const { return Metadata(*this); }
  inline __attribute__((always_inline)) Metadata metadata() { return Metadata(*this); }
  SoAPositionTemplate<ALIGNMENT> position() { return position_; }
  SoAPCATemplate<ALIGNMENT> pca() { return pca_; }
  struct ConstView {
    friend struct View;
    struct Metadata {
      friend ConstView;
      inline __attribute__((always_inline)) std::array<size_type, blocksNumber> size() const { return parent_.sizes_; }
      Metadata& operator=(const Metadata&) = delete;
      Metadata(const Metadata&) = delete;

    private:
      inline __attribute__((always_inline)) Metadata(const ConstView& _soa_impl_parent) : parent_(_soa_impl_parent) {}
      const ConstView& parent_;
    };
    friend Metadata;
    inline __attribute__((always_inline)) const Metadata metadata() const { return Metadata(*this); }
    ConstView() = default;
    ConstView(ConstView const&) = default;
    ConstView& operator=(ConstView const&) = default;
    ConstView(ConstView&&) = default;
    ConstView& operator=(ConstView&&) = default;
    ~ConstView() = default;
    ConstView(SoAGenericBlocksTemplate& blocks)
        : positionView_(blocks.position_), pcaView_(blocks.pca_), sizes_{blocks.sizes_} {}
    ConstView(SoAPositionTemplate<ALIGNMENT>::ConstView position, SoAPCATemplate<ALIGNMENT>::ConstView pca)
        : positionView_{position},
          pcaView_{pca},
          sizes_{{positionView_.metadata().size(), pcaView_.metadata().size()}} {}
    const SoAPositionTemplate<ALIGNMENT>::ConstView position() const { return positionView_; }
    const SoAPCATemplate<ALIGNMENT>::ConstView pca() const { return pcaView_; }

  private:
    SoAPositionTemplate<ALIGNMENT>::ConstView positionView_;
    SoAPCATemplate<ALIGNMENT>::ConstView pcaView_;
    std::array<size_type, blocksNumber> sizes_;
  };
  struct View : ConstView {
    using base_type = ConstView;
    struct Metadata {
      friend View;
      inline __attribute__((always_inline)) std::array<size_type, blocksNumber> size() const { return parent_.sizes_; }
      Metadata& operator=(const Metadata&) = delete;
      Metadata(const Metadata&) = delete;

    private:
      inline __attribute__((always_inline)) Metadata(const View& _soa_impl_parent) : parent_(_soa_impl_parent) {}
      const View& parent_;
    };
    friend Metadata;
    inline __attribute__((always_inline)) const Metadata metadata() const { return Metadata(*this); }
    inline __attribute__((always_inline)) Metadata metadata() { return Metadata(*this); }
    View() = default;
    View(View const&) = default;
    View& operator=(View const&) = default;
    View(View&&) = default;
    View& operator=(View&&) = default;
    ~View() = default;
    View(SoAGenericBlocksTemplate& blocks) : base_type{blocks} {}
    View(SoAPositionTemplate<ALIGNMENT>::View position, SoAPCATemplate<ALIGNMENT>::View pca)
        : base_type{position, pca} {}
    SoAPositionTemplate<ALIGNMENT>::View position() {
      return SoAPositionTemplate<ALIGNMENT>::const_cast_View(base_type::positionView_);
    }
    SoAPCATemplate<ALIGNMENT>::View pca() { return SoAPCATemplate<ALIGNMENT>::const_cast_View(base_type::pcaView_); }
  };
  struct Descriptor;
  struct ConstDescriptor;
  SoAGenericBlocksTemplate() : sizes_{}, position_(), pca_() {}
  SoAGenericBlocksTemplate(std::byte* mem, std::array<size_type, blocksNumber> elements) : sizes_(elements) {
    byte_size_type offset = 0;
    size_type index = 0;
    position_ = SoAPositionTemplate<ALIGNMENT>(mem + offset, sizes_[index]);
    offset += SoAPositionTemplate<ALIGNMENT>::computeDataSize(sizes_[index]);
    index++;
    pca_ = SoAPCATemplate<ALIGNMENT>(mem + offset, sizes_[index]);
    offset += SoAPCATemplate<ALIGNMENT>::computeDataSize(sizes_[index]);
    index++;
  }
  SoAGenericBlocksTemplate(SoAGenericBlocksTemplate const& _soa_impl_other)
      : sizes_(_soa_impl_other.sizes_), position_(_soa_impl_other.position_), pca_(_soa_impl_other.pca_) {}
  SoAGenericBlocksTemplate& operator=(SoAGenericBlocksTemplate const& _soa_impl_other) {
    sizes_ = _soa_impl_other.sizes_;
    position_ = _soa_impl_other.position_;
    pca_ = _soa_impl_other.pca_;
    return *this;
  }
  void deepCopy(ConstView const& view) {
    size_type index = 0;
    if (sizes_[index] < view.position().metadata().size()) {
      throw std::runtime_error(
          "In "
          "SoAGenericBlocksTemplate"
          "::deepCopy method: number of elements mismatch for block "
          "position"
          "");
    }
    index++;
    if (sizes_[index] < view.pca().metadata().size()) {
      throw std::runtime_error(
          "In "
          "SoAGenericBlocksTemplate"
          "::deepCopy method: number of elements mismatch for block "
          "pca"
          "");
    }
    index++;
    position_.deepCopy(view.position());
    pca_.deepCopy(view.pca());
  }
  template <typename T>
  void ROOTReadStreamer(T& onfile) {
    position_.ROOTReadStreamer(onfile);
    pca_.ROOTReadStreamer(onfile);
  }
  void ROOTStreamerCleaner() {
    position_.ROOTStreamerCleaner();
    pca_.ROOTStreamerCleaner();
  }

private:
  static constexpr std::pair<size_type, size_type> computeMethodsNumber() {
    size_type _soa_methods_count = 0;
    size_type _soa_const_methods_count = 0;
    return {_soa_methods_count, _soa_const_methods_count};
  }
  static_assert(computeMethodsNumber().first <= 1,
                "There can be at most one SOA_VIEW_METHODS macro."
                "Please declare all your methods inside the same macro.");
  static_assert(computeMethodsNumber().second <= 1,
                "There can be at most one SOA_CONST_VIEW_METHODS macro."
                "Please declare all your methods inside the same macro.");
  std::array<size_type, blocksNumber> sizes_;
  SoAPositionTemplate<ALIGNMENT> position_;
  SoAPCATemplate<ALIGNMENT> pca_;
};

@cmsbuild
Copy link
Contributor

cmsbuild commented Jul 24, 2025

cms-bot internal usage

@cmsbuild
Copy link
Contributor

+code-checks

Logs: https://cmssdt.cern.ch/SDT/code-checks/cms-sw-PR-48629/45595

@cmsbuild
Copy link
Contributor

A new Pull Request was created by @leobeltra for master.

It involves the following packages:

  • DataFormats/Portable (heterogeneous)
  • DataFormats/SoATemplate (heterogeneous)

@cmsbuild, @fwyzard, @makortel can you please review it and eventually sign? Thanks.
@missirol, @mmusich, @rovere this is something you requested to watch as well.
@antoniovilela, @mandrenguyen, @rappoccio, @sextonkennedy you are the release manager for this.

cms-bot commands are listed here


template <typename L = Layout>
requires requires { L::blocksNumber; }
PortableDeviceCollection(std::array<int32_t, L::blocksNumber> elements, TDev const& device)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is elements passed by value on purpose, or would it benefit from being a const reference?

@cmsbuild
Copy link
Contributor

+code-checks

Logs: https://cmssdt.cern.ch/SDT/code-checks/cms-sw-PR-48629/45599

@cmsbuild
Copy link
Contributor

Pull request #48629 was updated. @cmsbuild, @fwyzard, @makortel can you please check and sign again.

@fwyzard
Copy link
Contributor

fwyzard commented Jul 25, 2025

please test

@cmsbuild
Copy link
Contributor

+1

Size: This PR adds an extra 64KB to repository
Summary: https://cmssdt.cern.ch/SDT/jenkins-artifacts/pull-request-integration/PR-31c0b8/47387/summary.html
COMMIT: cfa7678
CMSSW: CMSSW_15_1_X_2025-07-24-2300/el8_amd64_gcc12
User test area: For local testing, you can use /cvmfs/cms-ci.cern.ch/week1/cms-sw/cmssw/48629/47387/install.sh to create a dev area with all the needed externals and cmssw changes.

Comparison Summary

Summary:

  • You potentially added 1 lines to the logs
  • Reco comparison results: 1 differences found in the comparisons
  • DQMHistoTests: Total files compared: 50
  • DQMHistoTests: Total histograms compared: 4076162
  • DQMHistoTests: Total failures: 45
  • DQMHistoTests: Total nulls: 0
  • DQMHistoTests: Total successes: 4076097
  • DQMHistoTests: Total skipped: 20
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 49 files compared)
  • Checked 215 log files, 184 edm output root files, 50 DQM output files
  • TriggerResults: no differences found

@cmsbuild
Copy link
Contributor

Pull request #48629 was updated. @cmsbuild, @fwyzard, @makortel can you please check and sign again.

@cmsbuild
Copy link
Contributor

+code-checks

Logs: https://cmssdt.cern.ch/SDT/code-checks/cms-sw-PR-48629/46742

@cmsbuild
Copy link
Contributor

Pull request #48629 was updated. @cmsbuild, @fwyzard, @makortel can you please check and sign again.

@fwyzard
Copy link
Contributor

fwyzard commented Nov 11, 2025

please test

@fwyzard
Copy link
Contributor

fwyzard commented Nov 11, 2025

+heterogeneous

Any changes, updates, refinements etc can be done in follow up PRs.

@cmsbuild
Copy link
Contributor

This pull request is fully signed and it will be integrated in one of the next master IBs after it passes the integration tests. This pull request will now be reviewed by the release team before it's merged. @mandrenguyen, @sextonkennedy, @ftenchini (and backports should be raised in the release meeting by the corresponding L2)

@cmsbuild
Copy link
Contributor

+1

Size: This PR adds an extra 28KB to repository
Summary: https://cmssdt.cern.ch/SDT/jenkins-artifacts/pull-request-integration/PR-31c0b8/49400/summary.html
COMMIT: e9bc89c
CMSSW: CMSSW_16_0_X_2025-11-10-2300/el8_amd64_gcc13
Additional Tests: GPU,AMD_MI300X,AMD_W7900,NVIDIA_H100,NVIDIA_L40S,NVIDIA_T4
User test area: For local testing, you can use /cvmfs/cms-ci.cern.ch/week1/cms-sw/cmssw/48629/49400/install.sh to create a dev area with all the needed externals and cmssw changes.

Comparison Summary

Summary:

  • You potentially removed 3 lines from the logs
  • ROOTFileChecks: Some differences in event products or their sizes found
  • Reco comparison results: 6 differences found in the comparisons
  • Reco comparison had 2 failed jobs
  • DQMHistoTests: Total files compared: 51
  • DQMHistoTests: Total histograms compared: 3939953
  • DQMHistoTests: Total failures: 50
  • DQMHistoTests: Total nulls: 0
  • DQMHistoTests: Total successes: 3939883
  • DQMHistoTests: Total skipped: 20
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 50 files compared)
  • Checked 218 log files, 188 edm output root files, 51 DQM output files
  • TriggerResults: no differences found

AMD_MI300X Comparison Summary

Summary:

  • You potentially removed 1 lines from the logs
  • Reco comparison results: 223 differences found in the comparisons
  • Reco comparison had 6 failed jobs
  • DQMHistoTests: Total files compared: 11
  • DQMHistoTests: Total histograms compared: 148553
  • DQMHistoTests: Total failures: 30976
  • DQMHistoTests: Total nulls: 12
  • DQMHistoTests: Total successes: 117565
  • DQMHistoTests: Total skipped: 0
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 10 files compared)
  • Checked 42 log files, 45 edm output root files, 11 DQM output files
  • TriggerResults: no differences found

AMD_W7900 Comparison Summary

Summary:

  • You potentially removed 4 lines from the logs
  • Reco comparison results: 217 differences found in the comparisons
  • Reco comparison had 6 failed jobs
  • DQMHistoTests: Total files compared: 11
  • DQMHistoTests: Total histograms compared: 148553
  • DQMHistoTests: Total failures: 34082
  • DQMHistoTests: Total nulls: 11
  • DQMHistoTests: Total successes: 114460
  • DQMHistoTests: Total skipped: 0
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 10 files compared)
  • Checked 42 log files, 45 edm output root files, 11 DQM output files
  • TriggerResults: no differences found

NVIDIA_H100 Comparison Summary

Summary:

  • You potentially removed 6 lines from the logs
  • Reco comparison results: 237 differences found in the comparisons
  • Reco comparison had 6 failed jobs
  • DQMHistoTests: Total files compared: 11
  • DQMHistoTests: Total histograms compared: 148553
  • DQMHistoTests: Total failures: 26963
  • DQMHistoTests: Total nulls: 12
  • DQMHistoTests: Total successes: 121578
  • DQMHistoTests: Total skipped: 0
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 10 files compared)
  • Checked 42 log files, 45 edm output root files, 11 DQM output files
  • TriggerResults: no differences found

NVIDIA_L40S Comparison Summary

Summary:

  • You potentially added 6 lines to the logs
  • Reco comparison results: 243 differences found in the comparisons
  • Reco comparison had 6 failed jobs
  • DQMHistoTests: Total files compared: 11
  • DQMHistoTests: Total histograms compared: 148553
  • DQMHistoTests: Total failures: 26618
  • DQMHistoTests: Total nulls: 10
  • DQMHistoTests: Total successes: 121925
  • DQMHistoTests: Total skipped: 0
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 10 files compared)
  • Checked 42 log files, 45 edm output root files, 11 DQM output files
  • TriggerResults: found differences in 1 / 10 workflows

NVIDIA_T4 Comparison Summary

Summary:

  • You potentially added 3 lines to the logs
  • Reco comparison results: 268 differences found in the comparisons
  • Reco comparison had 6 failed jobs
  • DQMHistoTests: Total files compared: 11
  • DQMHistoTests: Total histograms compared: 148553
  • DQMHistoTests: Total failures: 27361
  • DQMHistoTests: Total nulls: 7
  • DQMHistoTests: Total successes: 121185
  • DQMHistoTests: Total skipped: 0
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 10 files compared)
  • Checked 42 log files, 45 edm output root files, 11 DQM output files
  • TriggerResults: found differences in 1 / 10 workflows

@ftenchini
Copy link

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants