LCOV - code coverage report
Current view: top level - core/include/scipp/core - transform_common.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 10 10 100.0 %
Date: 2024-04-28 01:25:40 Functions: 39 94 41.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             : 
       7             : #include <tuple>
       8             : 
       9             : #include "scipp/common/overloaded.h"
      10             : #include "scipp/core/except.h"
      11             : #include "scipp/core/value_and_variance.h"
      12             : #include "scipp/core/values_and_variances.h"
      13             : 
      14             : namespace scipp::core {
      15             : 
      16             : template <class... Ts> struct pair_self {
      17             :   using type = std::tuple<std::tuple<Ts, Ts>...>;
      18             : };
      19             : template <class... Ts> struct pair_custom {
      20             :   using type = std::tuple<Ts...>;
      21             : };
      22             : template <class... Ts> struct pair_ {
      23             :   template <class RHS> using type = std::tuple<std::tuple<Ts, RHS>...>;
      24             : };
      25             : 
      26             : template <class... Ts> using pair_self_t = typename pair_self<Ts...>::type;
      27             : template <class... Ts> using pair_custom_t = typename pair_custom<Ts...>::type;
      28             : 
      29             : template <class... Ts> struct pair_product {
      30             :   template <class T> using type = std::tuple<std::tuple<T, Ts>...>;
      31             : };
      32             : 
      33             : template <class... Ts>
      34             : using pair_product_t = decltype(std::tuple_cat(
      35             :     typename pair_product<Ts...>::template type<Ts>{}...));
      36             : 
      37             : using arithmetic_type_pairs = pair_product_t<float, double, int32_t, int64_t>;
      38             : using arithmetic_type_pairs_with_bool =
      39             :     pair_product_t<float, double, int32_t, int64_t, bool>;
      40             : 
      41             : static constexpr auto keep_unit =
      42             :     overloaded{[](const units::Unit &) {},
      43             :                [](const units::Unit &, const units::Unit &) {}};
      44             : 
      45             : static constexpr auto dimensionless_unit_check =
      46             :     [](units::Unit &varUnit, const units::Unit &otherUnit) {
      47             :       expect::equals(units::one, varUnit);
      48             :       expect::equals(units::one, otherUnit);
      49             :     };
      50             : 
      51             : static constexpr auto dimensionless_unit_check_return =
      52       29111 :     overloaded{[](const units::Unit &a) {
      53       29116 :                  expect::equals(units::one, a);
      54       29106 :                  return units::one;
      55             :                },
      56         269 :                [](const units::Unit &a, const units::Unit &b) {
      57         269 :                  expect::equals(units::one, a);
      58         269 :                  expect::equals(units::one, b);
      59         269 :                  return units::one;
      60             :                }};
      61             : 
      62             : template <typename Op> struct assign_unary : Op {
      63             :   template <typename Out, typename... In>
      64         145 :   void operator()(Out &out, In &&...in) {
      65         145 :     out = Op::operator()(std::forward<In>(in)...);
      66         145 :   }
      67             : };
      68             : template <typename Op> assign_unary(Op) -> assign_unary<Op>;
      69             : 
      70             : /// Flags for transform, added as overloads to the operator. These are never
      71             : /// actually called since flag presence is checked via the base class of the
      72             : /// operator.
      73             : namespace transform_flags {
      74             : 
      75             : /// Base and NULL flag. Do not test for this type.
      76             : struct Flag {
      77             :   void operator()() const {};
      78             : };
      79             : 
      80             : /// Helper to conditionally apply a given flag under condition (B) otherwise
      81             : /// Null Flag
      82             : template <bool B>
      83             : constexpr auto conditional_flag =
      84             :     [](auto flag) { return std::conditional_t<B, decltype(flag), Flag>{}; };
      85             : 
      86             : namespace {
      87             : 
      88             : struct no_out_variance_t : Flag {};
      89             : /// Add this to overloaded operator to indicate that the operation does not
      90             : /// return data with variances, regardless of whether inputs have variances.
      91             : constexpr auto no_out_variance = no_out_variance_t{};
      92             : 
      93             : template <int N> struct expect_no_variance_arg_t : Flag {};
      94             : /// Add this to overloaded operator to indicate that the operation does not
      95             : /// support variances in the specified argument.
      96             : template <int N>
      97             : constexpr auto expect_no_variance_arg = expect_no_variance_arg_t<N>{};
      98             : 
      99             : struct expect_no_in_variance_if_out_cannot_have_variance_t : Flag {};
     100             : /// Add this to overloaded operator to indicate that if the output dtype
     101             : /// does not support variance none of the inputs should have a variance.
     102             : constexpr auto expect_no_in_variance_if_out_cannot_have_variance =
     103             :     expect_no_in_variance_if_out_cannot_have_variance_t{};
     104             : 
     105             : template <int N> struct expect_variance_arg_t : Flag {};
     106             : /// Add this to overloaded operator to indicate that the operation requires
     107             : /// variances in the specified argument.
     108             : template <int N>
     109             : constexpr auto expect_variance_arg = expect_variance_arg_t<N>{};
     110             : 
     111             : struct expect_in_variance_if_out_variance_t : Flag {};
     112             : /// Add this to overloaded operator to indicate that the in-place operation
     113             : /// requires inputs to have a variance if the output has a variance.
     114             : constexpr auto expect_in_variance_if_out_variance =
     115             :     expect_in_variance_if_out_variance_t{};
     116             : 
     117             : struct expect_all_or_none_have_variance_t : Flag {};
     118             : constexpr auto expect_all_or_none_have_variance =
     119             :     expect_all_or_none_have_variance_t{};
     120             : 
     121             : struct force_variance_broadcast_t : Flag {};
     122             : /// Add this to overloaded operator to indicate to skip the check for variance
     123             : /// broadcast. This is used to implement "copy", which we want to work on
     124             : /// explicitly broadcasted inputs, even in the presence of variances.
     125             : constexpr auto force_variance_broadcast = force_variance_broadcast_t{};
     126             : 
     127             : } // namespace
     128             : } // namespace transform_flags
     129             : 
     130             : } // namespace scipp::core

Generated by: LCOV version 1.14