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 : #pragma once 6 : #include "scipp/core/dimensions.h" 7 : #include "scipp/core/element_array_view.h" 8 : #include "scipp/core/except.h" 9 : #include "scipp/units/unit.h" 10 : #include "scipp/variable/element_array_model.h" 11 : #include "scipp/variable/except.h" 12 : #include "scipp/variable/transform.h" 13 : #include "scipp/variable/variable_concept.h" 14 : 15 : namespace scipp::variable { 16 : 17 : /// Implementation of VariableConcept that represents an array with structured 18 : /// elements of type T. 19 : /// 20 : /// The difference to ElementArrayModel is that this class allows for creating 21 : /// variables that share ownership of the underlying structure elements, e.g., 22 : /// to provide access to an array of vector elements from an array of vectors. 23 : template <class T, class Elem> 24 : class StructureArrayModel : public VariableConcept { 25 : public: 26 : using value_type = T; 27 : using element_type = Elem; 28 : static constexpr scipp::index element_count = sizeof(T) / sizeof(Elem); 29 : static_assert(sizeof(Elem) * element_count == sizeof(T)); 30 : 31 327092 : StructureArrayModel(const scipp::index size, const units::Unit &unit, 32 : element_array<Elem> model) 33 : : VariableConcept(units::one), // unit ignored 34 327092 : m_elements(std::make_shared<ElementArrayModel<Elem>>( 35 654184 : size * element_count, unit, std::move(model))) {} 36 : 37 1 : StructureArrayModel(VariableConceptHandle &&elements) 38 : : VariableConcept(units::one), // unit ignored 39 1 : m_elements(std::move(elements)) {} 40 : 41 : ~StructureArrayModel() override; 42 : 43 0 : static DType static_dtype() noexcept { return scipp::dtype<T>; } 44 5956918 : DType dtype() const noexcept override { return scipp::dtype<T>; } 45 318442 : scipp::index size() const override { 46 318442 : return m_elements->size() / element_count; 47 : } 48 : 49 652193 : const units::Unit &unit() const override { return m_elements->unit(); } 50 56731 : void setUnit(const units::Unit &unit) override { m_elements->setUnit(unit); } 51 : 52 : VariableConceptHandle 53 : makeDefaultFromParent(const scipp::index size) const override; 54 : 55 : VariableConceptHandle 56 0 : makeDefaultFromParent(const Variable &shape) const override { 57 0 : return makeDefaultFromParent(shape.dims().volume()); 58 : } 59 : 60 : [[nodiscard]] bool equals(const Variable &a, 61 : const Variable &b) const override; 62 : [[nodiscard]] bool equals_nan(const Variable &a, 63 : const Variable &b) const override; 64 : void copy(const Variable &src, Variable &dest) const override; 65 : void copy(const Variable &src, Variable &&dest) const override; 66 : void assign(const VariableConcept &other) override; 67 : 68 1098092 : bool has_variances() const noexcept override { return false; } 69 0 : void setVariances(const Variable &) override { 70 0 : except::throw_cannot_have_variances(core::dtype<T>); 71 : } 72 : 73 1 : VariableConceptHandle clone() const override { 74 1 : return std::make_shared<StructureArrayModel<T, Elem>>(m_elements->clone()); 75 : } 76 : 77 681875 : auto values(const core::ElementArrayViewParams &base) const { 78 681875 : return ElementArrayView(base, get_values()); 79 : } 80 419253 : auto values(const core::ElementArrayViewParams &base) { 81 419253 : return ElementArrayView(base, get_values()); 82 : } 83 : 84 49181 : VariableConceptHandle elements() const { return m_elements; } 85 : 86 4 : scipp::index dtype_size() const override { return sizeof(T); } 87 4 : scipp::index object_size() const override { 88 4 : return sizeof(*this) + m_elements->object_size(); 89 : } 90 0 : const VariableConceptHandle &bin_indices() const override { 91 0 : throw except::TypeError("This data type does not have bin indices."); 92 : } 93 : 94 14 : scipp::span<const T> values() const { 95 14 : return {get_values(), static_cast<size_t>(size())}; 96 : } 97 0 : scipp::span<T> values() { 98 0 : return {get_values(), static_cast<size_t>(size())}; 99 : } 100 : 101 : private: 102 : const T *get_values() const; 103 : T *get_values(); 104 : VariableConceptHandle m_elements; 105 : }; 106 : 107 : template <class T, class Elem> 108 15429 : VariableConceptHandle StructureArrayModel<T, Elem>::makeDefaultFromParent( 109 : const scipp::index size) const { 110 : return std::make_shared<StructureArrayModel<T, Elem>>( 111 15429 : size, unit(), element_array<Elem>(size * element_count)); 112 : } 113 : 114 : template <class T, class Elem> 115 4016 : bool StructureArrayModel<T, Elem>::equals(const Variable &a, 116 : const Variable &b) const { 117 8032 : return a.dtype() == dtype() && b.dtype() == dtype() && 118 8032 : a.elements<T>() == b.elements<T>(); 119 : } 120 : 121 : template <class T, class Elem> 122 1 : bool StructureArrayModel<T, Elem>::equals_nan(const Variable &a, 123 : const Variable &b) const { 124 2 : return a.dtype() == dtype() && b.dtype() == dtype() && 125 2 : variable::equals_nan(a.elements<T>(), b.elements<T>()); 126 : } 127 : 128 : template <class T, class Elem> 129 56697 : void StructureArrayModel<T, Elem>::copy(const Variable &src, 130 : Variable &dest) const { 131 56697 : transform_in_place<T>( 132 11887605 : dest, src, [](auto &a, const auto &b) { a = b; }, "copy"); 133 56696 : } 134 : template <class T, class Elem> 135 0 : void StructureArrayModel<T, Elem>::copy(const Variable &src, 136 : Variable &&dest) const { 137 0 : copy(src, dest); 138 0 : } 139 : 140 : } // namespace scipp::variable