LCOV - code coverage report
Current view: top level - variable/include/scipp/variable - element_array_model.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 42 50 84.0 %
Date: 2024-04-28 01:25:40 Functions: 253 1032 24.5 %

          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 <optional>
       7             : 
       8             : #include "scipp/common/initialization.h"
       9             : #include "scipp/common/numeric.h"
      10             : #include "scipp/core/dimensions.h"
      11             : #include "scipp/core/eigen.h"
      12             : #include "scipp/core/element_array_view.h"
      13             : #include "scipp/core/except.h"
      14             : #include "scipp/units/unit.h"
      15             : #include "scipp/variable/except.h"
      16             : #include "scipp/variable/transform.h"
      17             : #include "scipp/variable/variable_concept.h"
      18             : 
      19             : namespace scipp::variable {
      20             : 
      21             : template <class T> struct is_span : std::false_type {};
      22             : template <class T> struct is_span<scipp::span<T>> : std::true_type {};
      23             : template <class T> inline constexpr bool is_span_v = is_span<T>::value;
      24             : 
      25             : template <class T1, class T2>
      26      549703 : bool equals_impl(const T1 &view1, const T2 &view2) {
      27             :   // TODO Use optimizations in case of contiguous views (instead of slower
      28             :   // ElementArrayView iteration). Add multi threading?
      29             :   if constexpr (is_span_v<typename T1::value_type>)
      30           0 :     return std::equal(
      31             :         view1.begin(), view1.end(), view2.begin(), view2.end(),
      32           0 :         [](const auto &a, const auto &b) { return equals_impl(a, b); });
      33             :   else
      34      549703 :     return std::equal(view1.begin(), view1.end(), view2.begin(), view2.end());
      35             : }
      36             : 
      37        7734 : template <class T> bool equals_nan(const T &a, const T &b) {
      38             :   if constexpr (std::is_floating_point_v<T>) {
      39             :     using numeric::isnan;
      40        6845 :     if (isnan(a) && isnan(b))
      41          63 :       return true;
      42             :   }
      43        7671 :   return a == b;
      44             : }
      45             : 
      46             : template <class T1, class T2>
      47        2225 : bool equals_nan_impl(const T1 &view1, const T2 &view2) {
      48             :   // TODO Use optimizations in case of contiguous views (instead of slower
      49             :   // ElementArrayView iteration). Add multi threading?
      50             :   if constexpr (is_span_v<typename T1::value_type>)
      51           0 :     return std::equal(
      52             :         view1.begin(), view1.end(), view2.begin(), view2.end(),
      53           0 :         [](const auto &a, const auto &b) { return equals_nan_impl(a, b); });
      54             :   else
      55        2225 :     return std::equal(
      56             :         view1.begin(), view1.end(), view2.begin(), view2.end(),
      57       10058 :         [](const auto &x, const auto &y) { return equals_nan(x, y); });
      58             : }
      59             : 
      60             : /// Implementation of VariableConcept that holds an array with element type T.
      61             : template <class T> class ElementArrayModel : public VariableConcept {
      62             : public:
      63             :   static_assert(!core::is_structured(core::template dtype<T>));
      64             :   using value_type = T;
      65             : 
      66             :   ElementArrayModel(const scipp::index size, const units::Unit &unit,
      67             :                     element_array<T> model,
      68             :                     std::optional<element_array<T>> variances = std::nullopt);
      69             : 
      70          15 :   static DType static_dtype() noexcept { return scipp::dtype<T>; }
      71    53571942 :   DType dtype() const noexcept override { return scipp::dtype<T>; }
      72      390556 :   scipp::index size() const override { return m_values.size(); }
      73             : 
      74             :   VariableConceptHandle
      75             :   makeDefaultFromParent(const scipp::index size) const override;
      76             : 
      77             :   VariableConceptHandle
      78           0 :   makeDefaultFromParent(const Variable &shape) const override {
      79           0 :     return makeDefaultFromParent(shape.dims().volume());
      80             :   }
      81             : 
      82             :   bool equals(const Variable &a, const Variable &b) const override;
      83             :   bool equals_nan(const Variable &a, const Variable &b) const override;
      84             :   void copy(const Variable &src, Variable &dest) const override;
      85             :   void copy(const Variable &src, Variable &&dest) const override;
      86             :   void assign(const VariableConcept &other) override;
      87             : 
      88             :   void setVariances(const Variable &variances) override;
      89             : 
      90             :   VariableConceptHandle clone() const override;
      91             : 
      92     8233331 :   bool has_variances() const noexcept override {
      93     8233331 :     return m_variances.has_value();
      94             :   }
      95             : 
      96     3736026 :   auto values(const core::ElementArrayViewParams &base) const {
      97     3736026 :     return ElementArrayView(base, m_values.data());
      98             :   }
      99     2619361 :   auto values(const core::ElementArrayViewParams &base) {
     100     2619361 :     return ElementArrayView(base, m_values.data());
     101             :   }
     102      318568 :   auto variances(const core::ElementArrayViewParams &base) const {
     103      318568 :     expect_has_variances();
     104      318567 :     return ElementArrayView(base, m_variances->data());
     105             :   }
     106       55219 :   auto variances(const core::ElementArrayViewParams &base) {
     107       55219 :     expect_has_variances();
     108       55217 :     return ElementArrayView(base, m_variances->data());
     109             :   }
     110             : 
     111        1486 :   scipp::index dtype_size() const override { return sizeof(T); }
     112        1517 :   scipp::index object_size() const override { return sizeof(*this); }
     113           0 :   const VariableConceptHandle &bin_indices() const override {
     114           0 :     throw except::TypeError("This data type does not have bin indices.");
     115             :   }
     116             : 
     117      681889 :   scipp::span<const T> values() const {
     118      681889 :     return {m_values.data(), m_values.data() + m_values.size()};
     119             :   }
     120             : 
     121      419253 :   scipp::span<T> values() {
     122      419253 :     return {m_values.data(), m_values.data() + m_values.size()};
     123             :   }
     124             : 
     125             : private:
     126      373787 :   void expect_has_variances() const {
     127      373787 :     if (!has_variances())
     128           3 :       throw except::VariancesError("Variable does not have variances.");
     129      373784 :   }
     130             :   element_array<T> m_values;
     131             :   std::optional<element_array<T>> m_variances;
     132             : };
     133             : 
     134             : namespace {
     135   110452144 : template <class T> auto copy(const T &x) { return x; }
     136   110452193 : constexpr auto do_copy = [](auto &a, const auto &b) { a = copy(b); };
     137             : } // namespace
     138             : 
     139             : /// Helper for implementing Variable(View) copy operations.
     140             : ///
     141             : /// This method is using virtual dispatch as a trick to obtain T, such that
     142             : /// transform can be called with any T.
     143             : template <class T>
     144      332456 : void ElementArrayModel<T>::copy(const Variable &src, Variable &dest) const {
     145      332456 :   transform_in_place<T>(
     146             :       dest, src,
     147             :       overloaded{core::transform_flags::expect_in_variance_if_out_variance,
     148             :                  core::transform_flags::force_variance_broadcast, do_copy},
     149             :       "copy");
     150      332431 : }
     151             : template <class T>
     152        5238 : void ElementArrayModel<T>::copy(const Variable &src, Variable &&dest) const {
     153        5238 :   copy(src, dest);
     154        5234 : }
     155             : 
     156             : } // namespace scipp::variable

Generated by: LCOV version 1.14