LCOV - code coverage report
Current view: top level - variable - util.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 64 67 95.5 %
Date: 2024-12-01 01:56:34 Functions: 10 11 90.9 %

          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/util.h"
       6             : #include "scipp/core/element/util.h"
       7             : #include "scipp/core/except.h"
       8             : #include "scipp/variable/accumulate.h"
       9             : #include "scipp/variable/arithmetic.h"
      10             : #include "scipp/variable/astype.h"
      11             : #include "scipp/variable/reduction.h"
      12             : #include "scipp/variable/subspan_view.h"
      13             : #include "scipp/variable/transform.h"
      14             : 
      15             : using namespace scipp::core;
      16             : 
      17             : namespace scipp::variable {
      18             : 
      19          49 : Variable linspace(const Variable &start, const Variable &stop, const Dim dim,
      20             :                   const scipp::index num) {
      21             :   // The implementation here is slightly verbose and explicit. It could be
      22             :   // improved if we were to introduce new variants of `transform`, similar to
      23             :   // `std::generate`.
      24          51 :   core::expect::equals(start.dims(), stop.dims());
      25          50 :   core::expect::equals(start.unit(), stop.unit());
      26          49 :   core::expect::equals(start.dtype(), stop.dtype());
      27          46 :   if (start.dtype() != dtype<double> && start.dtype() != dtype<float>)
      28           1 :     throw except::TypeError(
      29           2 :         "Cannot create linspace with non-floating-point start and/or stop.");
      30          45 :   if (start.has_variances() || stop.has_variances())
      31           3 :     throw except::VariancesError(
      32           6 :         "Cannot create linspace with start and/or stop containing variances.");
      33          42 :   auto dims = start.dims();
      34          42 :   dims.addInner(dim, num);
      35          42 :   Variable out(start, dims);
      36          42 :   const auto range = stop - start;
      37       72143 :   for (scipp::index i = 0; i < num - 1; ++i)
      38      216303 :     copy(start + astype(static_cast<double>(i) / (num - 1) * units::one,
      39      144202 :                         start.dtype()) *
      40             :                      range,
      41      144202 :          out.slice({dim, i}));
      42          42 :   copy(stop, out.slice({dim, num - 1})); // endpoint included
      43          84 :   return out;
      44          42 : }
      45             : 
      46        9818 : Variable islinspace(const Variable &var, const Dim dim) {
      47        9818 :   const auto con_var = as_contiguous(var, dim);
      48       19636 :   return transform(subspan_view(con_var, dim), core::element::islinspace,
      49       29454 :                    "islinspace");
      50        9818 : }
      51             : 
      52        4803 : Variable isarange(const Variable &var, const Dim dim) {
      53        9606 :   return transform(subspan_view(var, dim), core::element::isarange, "isarange");
      54             : }
      55             : 
      56             : /// Return a variable of True, if variable values are sorted along given dim.
      57             : ///
      58             : /// If `order` is SortOrder::Ascending, checks if values are non-decreasing.
      59             : /// If `order` is SortOrder::Descending, checks if values are non-increasing.
      60       10868 : Variable issorted(const Variable &x, const Dim dim, const SortOrder order) {
      61       10868 :   auto dims = x.dims();
      62       10868 :   dims.erase(dim);
      63       10866 :   auto out = variable::ones(dims, units::none, dtype<bool>);
      64       10866 :   const auto size = x.dims()[dim];
      65       10866 :   if (size < 2)
      66          69 :     return out;
      67       10797 :   if (order == SortOrder::Ascending)
      68       21108 :     accumulate_in_place(out, x.slice({dim, 0, size - 1}),
      69       21108 :                         x.slice({dim, 1, size}),
      70             :                         core::element::issorted_nondescending, "issorted");
      71             :   else
      72         486 :     accumulate_in_place(out, x.slice({dim, 0, size - 1}),
      73         486 :                         x.slice({dim, 1, size}),
      74             :                         core::element::issorted_nonascending, "issorted");
      75       10797 :   return out;
      76       10868 : }
      77             : 
      78             : /// Return true if variable values are sorted along given dim.
      79             : ///
      80             : /// If `order` is SortOrder::Ascending, checks if values are non-decreasing.
      81             : /// If `order` is SortOrder::Descending, checks if values are non-increasing.
      82       10855 : bool allsorted(const Variable &x, const Dim dim, const SortOrder order) {
      83       10855 :   return variable::all(issorted(x, dim, order)).value<bool>();
      84             : }
      85             : 
      86             : /// Zip elements of two variables into a variable where each element is a pair.
      87      250507 : Variable zip(const Variable &first, const Variable &second) {
      88      501014 :   return transform(astype(first, dtype<int64_t>, CopyPolicy::TryAvoid),
      89      501014 :                    astype(second, dtype<int64_t>, CopyPolicy::TryAvoid),
      90      751521 :                    core::element::zip, "zip");
      91             : }
      92             : 
      93             : /// For an input where elements are pairs, return two variables containing the
      94             : /// first and second components of the input pairs.
      95       22124 : std::pair<Variable, Variable> unzip(const Variable &var) {
      96       44248 :   return {var.elements<scipp::index_pair>("begin"),
      97       44248 :           var.elements<scipp::index_pair>("end")};
      98             : }
      99             : 
     100             : /// Fill variable with given values (and variances) and unit.
     101           0 : void fill(Variable &var, const Variable &value) {
     102           0 :   transform_in_place(var, value, core::element::fill, "fill");
     103           0 : }
     104             : 
     105             : /// Fill variable with zeros.
     106       22052 : void fill_zeros(Variable &var) {
     107       22052 :   transform_in_place(var, core::element::fill_zeros, "fill_zeros");
     108       22052 : }
     109             : 
     110             : /// Return elements chosen from x or y depending on condition.
     111        3218 : Variable where(const Variable &condition, const Variable &x,
     112             :                const Variable &y) {
     113        3218 :   return variable::transform(condition, x, y, element::where, "where");
     114             : }
     115             : 
     116      166216 : Variable as_contiguous(const Variable &var, const Dim dim) {
     117      166216 :   if (var.stride(dim) == 1)
     118      166175 :     return var;
     119          41 :   auto dims = var.dims();
     120          41 :   dims.erase(dim);
     121          41 :   dims.addInner(dim, var.dims()[dim]);
     122          82 :   return copy(transpose(var, dims.labels()));
     123          41 : }
     124             : 
     125             : } // namespace scipp::variable

Generated by: LCOV version 1.14