Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : #include "scipp/variable/bins.h" 6 : #include "scipp/variable/element_array_variable.tcc" 7 : #include "scipp/variable/structure_array_model.h" 8 : 9 : namespace scipp::variable { 10 : 11 : template <class T> 12 : constexpr auto structure_element_offset{ 13 : T::missing_specialization_of_structure_element_offset}; 14 : 15 : template <class T, class... Is> 16 49195 : Variable Variable::elements_impl(Is... index) const { 17 49195 : if (dtype() == core::dtype<core::bin<Variable>>) { 18 14 : const auto &[idx, dim, buf] = constituents<Variable>(); 19 14 : return make_bins_no_validate(idx, dim, buf.template elements<T>(index...)); 20 14 : } 21 49181 : constexpr auto N = model_t<T>::element_count; 22 49181 : auto elements(*this); 23 49181 : elements.m_object = cast<T>(*this).elements(); 24 : // Scale offset and strides (which refer to type T) so they are correct for 25 : // the *element type* of T. 26 49181 : elements.m_offset *= N; 27 167449 : for (scipp::index i = 0; i < dims().ndim(); ++i) 28 118268 : elements.m_strides[i] = N * strides()[i]; 29 : if constexpr (sizeof...(Is) == 0) { 30 : // Get all elements by setting up internal dim and stride 31 8245 : elements.unchecked_dims().addInner(Dim::InternalStructureComponent, N); 32 8245 : elements.unchecked_strides().push_back(1); 33 : } else { 34 : // Get specific element at offset 35 40936 : const auto offset = structure_element_offset<T>(index...); 36 40931 : if (offset < 0 || offset >= N) 37 0 : throw std::out_of_range("Bad offset"); 38 40931 : elements.m_offset += offset; 39 : } 40 49176 : return elements; 41 49181 : } 42 : 43 8251 : template <class T> Variable Variable::elements() const { 44 8251 : return elements_impl<T>(); 45 : } 46 : 47 40944 : template <class T> Variable Variable::elements(const std::string &key) const { 48 40944 : return elements_impl<T>(key); 49 : } 50 : 51 : template <class T, class Elem> 52 0 : void StructureArrayModel<T, Elem>::assign(const VariableConcept &other) { 53 0 : *this = requireT<const StructureArrayModel<T, Elem>>(other); 54 0 : } 55 : 56 : template <class T, class Elem> 57 681889 : const T *StructureArrayModel<T, Elem>::get_values() const { 58 : return reinterpret_cast<const T *>( 59 681889 : requireT<const ElementArrayModel<Elem>>(*m_elements).values().data()); 60 : } 61 : 62 419253 : template <class T, class Elem> T *StructureArrayModel<T, Elem>::get_values() { 63 : return reinterpret_cast<T *>( 64 419253 : requireT<ElementArrayModel<Elem>>(*m_elements).values().data()); 65 : } 66 : 67 : template <class T> struct arg_type; 68 : template <class T, class U> struct arg_type<T(U)> { 69 : using type = U; 70 : }; 71 : 72 : /// Instantiate Variable for structure dtype with element access. 73 : #define INSTANTIATE_STRUCTURE_ARRAY_VARIABLE(name, T, Elem) \ 74 : template <> struct model<arg_type<void(T)>::type> { \ 75 : using type = StructureArrayModel<arg_type<void(T)>::type, Elem>; \ 76 : }; \ 77 : template SCIPP_EXPORT Variable Variable::elements<arg_type<void(T)>::type>() \ 78 : const; \ 79 : template SCIPP_EXPORT Variable Variable::elements<arg_type<void(T)>::type>( \ 80 : const std::string &) const; \ 81 : template class SCIPP_EXPORT \ 82 : StructureArrayModel<arg_type<void(T)>::type, Elem>; \ 83 : INSTANTIATE_ELEMENT_ARRAY_VARIABLE_BASE(name, arg_type<void(T)>::type) 84 : 85 : } // namespace scipp::variable