LCOV - code coverage report
Current view: top level - variable/include/scipp/variable - variable.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 25 26 96.2 %
Date: 2024-04-28 01:25:40 Functions: 77 137 56.2 %

          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             : 
       7             : #include <optional>
       8             : #include <string>
       9             : #include <utility>
      10             : #include <vector>
      11             : 
      12             : #include "scipp-variable_export.h"
      13             : #include "scipp/common/index.h"
      14             : #include "scipp/units/unit.h"
      15             : 
      16             : #include "scipp/core/dimensions.h"
      17             : #include "scipp/core/dtype.h"
      18             : #include "scipp/core/element_array.h"
      19             : #include "scipp/core/element_array_view.h"
      20             : #include "scipp/core/except.h"
      21             : #include "scipp/core/slice.h"
      22             : #include "scipp/core/strides.h"
      23             : 
      24             : #include "scipp/variable/variable_keyword_arg_constructor.h"
      25             : 
      26             : namespace llnl::units {
      27             : class precise_measurement;
      28             : }
      29             : 
      30             : namespace scipp::variable {
      31             : 
      32             : class VariableConcept;
      33             : using VariableConceptHandle = std::shared_ptr<VariableConcept>;
      34             : 
      35             : /// Return the default unit (dimensionless or none) for a given dtype.
      36             : [[nodiscard]] SCIPP_VARIABLE_EXPORT units::Unit
      37             : default_unit_for(const DType type);
      38             : 
      39             : /// Variable is a type-erased handle to any data structure representing a
      40             : /// multi-dimensional array. In addition it has a unit and a set of dimension
      41             : /// labels.
      42             : class SCIPP_VARIABLE_EXPORT Variable {
      43             : public:
      44     2084367 :   Variable() = default;
      45             :   Variable(const Variable &parent, const Dimensions &dims);
      46             :   Variable(const Dimensions &dims, VariableConceptHandle data);
      47             :   template <class T>
      48             :   Variable(const std::optional<units::Unit> &unit, const Dimensions &dimensions,
      49             :            T values, std::optional<T> variances);
      50             :   explicit Variable(const llnl::units::precise_measurement &m);
      51             : 
      52             :   /// Keyword-argument constructor.
      53             :   ///
      54             :   /// This is equivalent to `makeVariable`, except that the dtype is passed at
      55             :   /// runtime as first argument instead of a template argument. `makeVariable`
      56             :   /// should be preferred where possible, since it generates less code.
      57             :   template <class... Ts> Variable(const DType &type, Ts &&...args);
      58             : 
      59     5938019 :   Variable(const Variable &other) = default;
      60     4354465 :   Variable(Variable &&other) noexcept = default;
      61             : 
      62             :   Variable &operator=(const Variable &other);
      63             :   Variable &operator=(Variable &&other);
      64             : 
      65    14817439 :   ~Variable() noexcept = default;
      66             : 
      67             :   [[nodiscard]] const units::Unit &unit() const;
      68             :   void setUnit(const units::Unit &unit);
      69             :   void expect_can_set_unit(const units::Unit &unit) const;
      70             : 
      71             :   [[nodiscard]] const Dimensions &dims() const;
      72             :   [[nodiscard]] Dim dim() const;
      73             :   [[nodiscard]] scipp::index ndim() const;
      74             : 
      75             :   [[nodiscard]] DType dtype() const;
      76             : 
      77             :   [[nodiscard]] scipp::span<const scipp::index> strides() const;
      78             :   [[nodiscard]] scipp::index stride(const Dim dim) const;
      79             :   [[nodiscard]] scipp::index offset() const;
      80             : 
      81             :   [[nodiscard]] bool has_variances() const;
      82             : 
      83             :   template <class T> ElementArrayView<const T> values() const;
      84             :   template <class T> ElementArrayView<T> values();
      85             :   template <class T> ElementArrayView<const T> variances() const;
      86             :   template <class T> ElementArrayView<T> variances();
      87       20370 :   template <class T> const auto &value() const {
      88       20370 :     core::expect::ndim_is(dims(), 0);
      89       20368 :     return values<T>()[0];
      90             :   }
      91             :   template <class T> const auto &variance() const {
      92             :     core::expect::ndim_is(dims(), 0);
      93             :     return variances<T>()[0];
      94             :   }
      95       25791 :   template <class T> auto &value() {
      96       25791 :     core::expect::ndim_is(dims(), 0);
      97       25791 :     return values<T>()[0];
      98             :   }
      99             :   template <class T> auto &variance() {
     100             :     core::expect::ndim_is(dims(), 0);
     101             :     return variances<T>()[0];
     102             :   }
     103             : 
     104             :   [[nodiscard]] Variable slice(Slice params) const;
     105             :   void validateSlice(const Slice &s, const Variable &data) const;
     106             :   [[maybe_unused]] Variable &setSlice(Slice params, const Variable &data);
     107             : 
     108             :   template <class T> Variable elements() const;
     109             :   template <class T> Variable elements(const std::string &key) const;
     110             : 
     111             :   [[nodiscard]] Variable
     112             :   rename_dims(const std::vector<std::pair<Dim, Dim>> &names,
     113             :               const bool fail_on_unknown = true) const;
     114             : 
     115             :   bool operator==(const Variable &other) const;
     116             :   bool operator!=(const Variable &other) const;
     117             : 
     118             :   [[nodiscard]] const VariableConcept &data() const && = delete;
     119             :   [[nodiscard]] const VariableConcept &data() const &;
     120             :   VariableConcept &data() && = delete;
     121             :   VariableConcept &data() &;
     122             :   [[nodiscard]] const VariableConceptHandle &data_handle() const;
     123             :   void setDataHandle(VariableConceptHandle object);
     124             : 
     125             :   void setVariances(const Variable &v);
     126             : 
     127             :   [[nodiscard]] core::ElementArrayViewParams array_params() const;
     128             : 
     129             :   [[nodiscard]] Variable bin_indices() const;
     130             :   template <class T> const T &bin_buffer() const;
     131             :   template <class T> T &bin_buffer();
     132             : 
     133             :   template <class T> std::tuple<Variable, Dim, T> constituents() const;
     134             :   template <class T> std::tuple<Variable, Dim, T> constituents();
     135             :   template <class T> std::tuple<Variable, Dim, T> to_constituents();
     136             : 
     137             :   [[nodiscard]] Variable broadcast(const Dimensions &target) const;
     138             :   [[nodiscard]] Variable fold(const Dim dim, const Dimensions &target) const;
     139             :   [[nodiscard]] Variable transpose(scipp::span<const Dim> order) const;
     140             : 
     141             :   [[nodiscard]] bool is_valid() const noexcept;
     142             :   [[nodiscard]] bool is_slice() const;
     143             :   [[nodiscard]] bool is_readonly() const noexcept;
     144             :   [[nodiscard]] bool is_same(const Variable &other) const noexcept;
     145             : 
     146             :   [[nodiscard]] bool is_aligned() const noexcept;
     147             :   void set_aligned(bool aligned) noexcept;
     148             : 
     149             :   [[nodiscard]] Variable as_const() const;
     150             : 
     151       43569 :   auto &unchecked_dims() { return m_dims; }
     152       24493 :   auto &unchecked_strides() { return m_strides; }
     153             : 
     154             : private:
     155             :   // Declared friend so gtest recognizes it
     156             :   friend SCIPP_VARIABLE_EXPORT std::ostream &operator<<(std::ostream &,
     157             :                                                         const Variable &);
     158             :   template <class... Ts, class... Args>
     159             :   static Variable construct(const DType &type, Args &&...args);
     160             :   template <class T, class... Index>
     161             :   Variable elements_impl(Index... index) const;
     162             : 
     163             :   void expect_writable() const;
     164             : 
     165             :   Dimensions m_dims;
     166             :   Strides m_strides;
     167             :   scipp::index m_offset{0};
     168             :   VariableConceptHandle m_object;
     169             :   bool m_readonly{false};
     170             :   bool m_aligned{true};
     171             : };
     172             : 
     173             : /// Factory function for Variable supporting "keyword arguments"
     174             : ///
     175             : /// Two styles are supported:
     176             : ///     makeVariable<ElementType>(Dims, Shape, Unit, Values<T1>, Variances<T2>)
     177             : /// or
     178             : ///     makeVariable<ElementType>(Dimensions, Unit, Values<T1>, Variances<T2>)
     179             : /// Unit, Values, or Variances can be omitted. The order of arguments is
     180             : /// arbitrary.
     181             : /// Example:
     182             : ///     makeVariable<float>(units::kg,
     183             : ///     Shape{1, 2}, Dims{Dim::X, Dim::Y}, Values{3, 4}).
     184             : ///
     185             : /// Relation between Dims, Shape, Dimensions and actual data are as follows:
     186             : /// 1. If neither Values nor Variances are provided, resulting Variable contains
     187             : ///    ONLY values of corresponding length.
     188             : /// 2. The Variances can't be provided without any Values.
     189             : /// 3. Non empty Values and/or Variances must be consistent with shape.
     190             : /// 4. If empty Values and/or Variances are provided, resulting Variable
     191             : ///    contains default initialized Values and/or Variances, the way to make
     192             : ///    Variable which contains both Values and Variances given length
     193             : ///    uninitialized is:
     194             : ///        makeVariable<T>(Dims{Dim::X}, Shape{5}, Values{}, Variances{});
     195      682747 : template <class T, class... Ts> Variable makeVariable(Ts &&...ts) {
     196      682747 :   detail::ArgParser<T> parser;
     197      682747 :   (parser.parse(std::forward<Ts>(ts)), ...);
     198     1365490 :   return std::make_from_tuple<Variable>(std::move(parser.args));
     199      682747 : }
     200             : 
     201             : template <class... Ts, class... Args>
     202       12574 : Variable Variable::construct(const DType &type, Args &&...args) {
     203       12574 :   std::array vars{core::dtype<Ts> == type
     204             :                       ? makeVariable<Ts>(std::forward<Args>(args)...)
     205             :                       : Variable()...};
     206       56031 :   for (auto &var : vars)
     207       56031 :     if (var.is_valid())
     208       25148 :       return var;
     209           0 :   throw except::TypeError("Unsupported dtype for constructing a Variable: " +
     210             :                           to_string(type));
     211       12574 : }
     212             : 
     213             : template <class... Ts>
     214       12574 : Variable::Variable(const DType &type, Ts &&...args)
     215             :     : Variable{construct<double, float, int64_t, int32_t, bool, std::string,
     216             :                          scipp::core::time_point, scipp::index_pair>(
     217       12574 :           type, std::forward<Ts>(args)...)} {}
     218             : 
     219             : [[nodiscard]] SCIPP_VARIABLE_EXPORT Variable copy(const Variable &var);
     220             : [[maybe_unused]] SCIPP_VARIABLE_EXPORT Variable &copy(const Variable &var,
     221             :                                                       Variable &out);
     222             : [[maybe_unused]] SCIPP_VARIABLE_EXPORT Variable copy(const Variable &var,
     223             :                                                      Variable &&out);
     224             : 
     225             : [[nodiscard]] SCIPP_VARIABLE_EXPORT bool equals_nan(const Variable &a,
     226             :                                                     const Variable &b);
     227             : } // namespace scipp::variable
     228             : 
     229             : namespace scipp::core {
     230             : template <> inline constexpr DType dtype<variable::Variable>{1000};
     231             : template <> inline constexpr DType dtype<bucket<variable::Variable>>{1001};
     232             : } // namespace scipp::core
     233             : 
     234             : namespace scipp {
     235             : using variable::Dims;
     236             : using variable::makeVariable;
     237             : using variable::Shape;
     238             : using variable::Values;
     239             : using variable::Variable;
     240             : using variable::Variances;
     241             : } // namespace scipp
     242             : 
     243             : #include "scipp/variable/arithmetic.h"
     244             : #include "scipp/variable/logical.h"

Generated by: LCOV version 1.14