LCOV - code coverage report
Current view: top level - variable/include/scipp/variable - element_array_variable.tcc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 68 73 93.2 %
Date: 2024-04-28 01:25:40 Functions: 331 774 42.8 %

          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/element_array_model.h"
       6             : #include "scipp/variable/variable.tcc"
       7             : 
       8             : namespace scipp::variable {
       9             : 
      10             : template <class T>
      11     1642272 : Variable make_default_init(const Dimensions &dims, const units::Unit &unit,
      12             :                            const bool variances) {
      13     1642272 :   if (variances && !core::canHaveVariances<T>())
      14           0 :     throw except::VariancesError("This data type cannot have variances.");
      15     1642272 :   const auto volume = dims.volume();
      16     1642272 :   VariableConceptHandle model;
      17             :   if constexpr (std::is_same_v<model_t<T>, ElementArrayModel<T>>) {
      18     1351904 :     if (variances)
      19       27755 :       model = std::make_shared<model_t<T>>(
      20       55510 :           volume, unit, element_array<T>(volume, core::init_for_overwrite),
      21       55510 :           element_array<T>(volume, core::init_for_overwrite));
      22             :     else
      23     1324149 :       model = std::make_shared<model_t<T>>(
      24     2648298 :           volume, unit, element_array<T>(volume, core::init_for_overwrite));
      25             :   } else {
      26             :     using Elem = typename model_t<T>::element_type;
      27      290368 :     model = std::make_shared<model_t<T>>(
      28             :         volume, unit,
      29      580736 :         element_array<Elem>(model_t<T>::element_count * volume,
      30             :                             core::init_for_overwrite));
      31             :   }
      32     3284544 :   return Variable(dims, std::move(model));
      33     1642272 : }
      34             : 
      35             : template <class T> class VariableMaker : public AbstractVariableMaker {
      36             :   using AbstractVariableMaker::create;
      37    13358274 :   bool is_bins() const override { return false; }
      38     1642272 :   Variable create(const DType, const Dimensions &dims, const units::Unit &unit,
      39             :                   const bool variances, const parent_list &) const override {
      40     1642272 :     return make_default_init<T>(dims, unit, variances);
      41             :   }
      42           0 :   Dim elem_dim(const Variable &) const override { return Dim::Invalid; }
      43    11051677 :   DType elem_dtype(const Variable &var) const override { return var.dtype(); }
      44     3076630 :   units::Unit elem_unit(const Variable &var) const override {
      45     3076630 :     return var.unit();
      46             :   }
      47      463808 :   void expect_can_set_elem_unit(const Variable &var,
      48             :                                 const units::Unit &u) const override {
      49      463808 :     var.expect_can_set_unit(u);
      50      463801 :   }
      51      463854 :   void set_elem_unit(Variable &var, const units::Unit &u) const override {
      52      463854 :     var.setUnit(u);
      53      463854 :   }
      54     6582448 :   bool has_variances(const Variable &var) const override {
      55     6582448 :     return var.has_variances();
      56             :   }
      57      281498 :   Variable empty_like(const Variable &prototype,
      58             :                       const std::optional<Dimensions> &shape,
      59             :                       const Variable &sizes) const override {
      60      281498 :     if (sizes.is_valid())
      61          15 :       throw except::TypeError(
      62             :           "Cannot specify sizes in `empty_like` for non-bin prototype.");
      63      281483 :     return create(prototype.dtype(), shape ? *shape : prototype.dims(),
      64      562966 :                   prototype.unit(), prototype.has_variances(), {});
      65             :   }
      66             : };
      67             : 
      68             : template <class T>
      69     2488111 : ElementArrayModel<T>::ElementArrayModel(
      70             :     const scipp::index size, const units::Unit &unit, element_array<T> model,
      71             :     std::optional<element_array<T>> variances)
      72             :     : VariableConcept(unit),
      73     2488163 :       m_values(model ? std::move(model)
      74       29274 :                      : element_array<T>(size, default_init<T>::value())),
      75     4976222 :       m_variances(std::move(variances)) {
      76     2488111 :   if (m_variances)
      77       37486 :     core::expect::canHaveVariances<T>();
      78     2488106 :   if (size != scipp::size(m_values))
      79           4 :     throw except::DimensionError("Creating Variable: data size does not match "
      80             :                                  "volume given by dimension extents.");
      81     2488102 :   if (m_variances && !*m_variances)
      82        8277 :     *m_variances = element_array<T>(size, default_init<T>::value());
      83     2488129 : }
      84             : 
      85           1 : template <class T> VariableConceptHandle ElementArrayModel<T>::clone() const {
      86           1 :   return std::make_shared<ElementArrayModel<T>>(*this);
      87             : }
      88             : 
      89             : template <class T>
      90             : VariableConceptHandle
      91       26538 : ElementArrayModel<T>::makeDefaultFromParent(const scipp::index size) const {
      92       26538 :   if (has_variances())
      93             :     return std::make_shared<ElementArrayModel<T>>(
      94          35 :         size, unit(), element_array<T>(size), element_array<T>(size));
      95             :   else
      96       26503 :     return std::make_shared<ElementArrayModel<T>>(size, unit(),
      97       26503 :                                                   element_array<T>(size));
      98             : }
      99             : 
     100             : /// Helper for implementing Variable::operator==.
     101             : ///
     102             : /// This method is using virtual dispatch as a trick to obtain T, such that
     103             : /// values<T> and variances<T> can be compared.
     104             : template <class T>
     105      382208 : bool ElementArrayModel<T>::equals(const Variable &a, const Variable &b) const {
     106     1146228 :   return equals_impl(a.values<T>(), b.values<T>()) &&
     107      381812 :          (!a.has_variances() ||
     108      906193 :           equals_impl(a.variances<T>(), b.variances<T>()));
     109             : }
     110             : 
     111             : /// Helper for implementing Variable::operator==.
     112             : ///
     113             : /// This method is using virtual dispatch as a trick to obtain T, such that
     114             : /// values<T> and variances<T> can be compared.
     115             : template <class T>
     116        2041 : bool ElementArrayModel<T>::equals_nan(const Variable &a,
     117             :                                       const Variable &b) const {
     118        5990 :   return equals_nan_impl(a.values<T>(), b.values<T>()) &&
     119        1908 :          (!a.has_variances() ||
     120        4203 :           equals_nan_impl(a.variances<T>(), b.variances<T>()));
     121             : }
     122             : 
     123             : template <class T>
     124           0 : void ElementArrayModel<T>::assign(const VariableConcept &other) {
     125           0 :   *this = requireT<const ElementArrayModel<T>>(other);
     126           0 : }
     127             : 
     128             : template <class T>
     129        3545 : void ElementArrayModel<T>::setVariances(const Variable &variances) {
     130        3545 :   if (!variances.is_valid())
     131          29 :     return m_variances.reset();
     132        3516 :   if (!core::canHaveVariances<T>())
     133           1 :     throw except::VariancesError("This data type cannot have variances.");
     134             :   // TODO Could move if refcount is 1?
     135        3515 :   if (variances.has_variances())
     136           2 :     throw except::VariancesError(
     137             :         "Cannot set variances from variable with variances.");
     138        7024 :   m_variances.emplace(
     139        3513 :       requireT<const ElementArrayModel>(variances.data()).m_values);
     140             : }
     141             : 
     142             : #define INSTANTIATE_ELEMENT_ARRAY_VARIABLE_BASE(name, ...)                     \
     143             :   template SCIPP_EXPORT Variable variable::make_default_init<__VA_ARGS__>(     \
     144             :       const Dimensions &, const units::Unit &, const bool);                    \
     145             :   INSTANTIATE_VARIABLE_BASE(name, __VA_ARGS__)                                 \
     146             :   namespace {                                                                  \
     147             :   auto register_variable_maker_##name((                                        \
     148             :       variableFactory().emplace(                                               \
     149             :           dtype<__VA_ARGS__>, std::make_unique<VariableMaker<__VA_ARGS__>>()), \
     150             :       0));                                                                     \
     151             :   }                                                                            \
     152             :   template SCIPP_EXPORT Variable::Variable(                                    \
     153             :       const std::optional<units::Unit> &, const Dimensions &,                  \
     154             :       element_array<__VA_ARGS__>, std::optional<element_array<__VA_ARGS__>>);  \
     155             :   template SCIPP_EXPORT ElementArrayView<const __VA_ARGS__>                    \
     156             :   Variable::variances() const;                                                 \
     157             :   template SCIPP_EXPORT ElementArrayView<__VA_ARGS__> Variable::variances();
     158             : 
     159             : /// Macro for instantiating classes and functions required for support a new
     160             : /// dtype in Variable.
     161             : #define INSTANTIATE_ELEMENT_ARRAY_VARIABLE(name, ...)                          \
     162             :   template class SCIPP_EXPORT ElementArrayModel<__VA_ARGS__>;                  \
     163             :   INSTANTIATE_ELEMENT_ARRAY_VARIABLE_BASE(name, __VA_ARGS__)
     164             : 
     165             : } // namespace scipp::variable

Generated by: LCOV version 1.14