LCOV - code coverage report
Current view: top level - core/include/scipp/core/element - special_values.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 41 45 91.1 %
Date: 2024-04-28 01:25:40 Functions: 38 72 52.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             : #pragma once
       6             : 
       7             : #include <cmath>
       8             : #include <type_traits>
       9             : 
      10             : #include "scipp/common/numeric.h"
      11             : #include "scipp/common/overloaded.h"
      12             : #include "scipp/core/eigen.h"
      13             : #include "scipp/core/element/arg_list.h"
      14             : #include "scipp/core/transform_common.h"
      15             : 
      16             : namespace scipp::core::element {
      17             : 
      18             : template <class... Extra>
      19             : constexpr auto special_value_args =
      20             :     arg_list<int32_t, int64_t, double, float, Extra...>;
      21             : 
      22             : // WARNING: When adding support for new spatial types (or other types containing
      23             : // floating-point elements) you must specialize numeric::isnan and friends.
      24             : constexpr auto isnan =
      25             :     overloaded{special_value_args<Eigen::Vector3d>,
      26          91 :                [](const auto x) {
      27             :                  using numeric::isnan;
      28          91 :                  return isnan(x);
      29             :                },
      30          39 :                [](const units::Unit &) { return units::none; }};
      31             : 
      32             : constexpr auto isinf =
      33             :     overloaded{special_value_args<Eigen::Vector3d>,
      34          21 :                [](const auto x) {
      35             :                  using numeric::isinf;
      36          21 :                  return isinf(x);
      37             :                },
      38          17 :                [](const units::Unit &) { return units::none; }};
      39             : 
      40             : constexpr auto isfinite =
      41             :     overloaded{special_value_args<Eigen::Vector3d>,
      42         870 :                [](const auto x) {
      43             :                  using numeric::isfinite;
      44         870 :                  return isfinite(x);
      45             :                },
      46         175 :                [](const units::Unit &) { return units::none; }};
      47             : 
      48             : namespace detail {
      49          19 : template <typename T> auto isposinf(T x) {
      50          19 :   return numeric::isinf(x) && !numeric::signbit(x);
      51             : }
      52             : 
      53          19 : template <typename T> auto isneginf(T x) {
      54          19 :   return numeric::isinf(x) && numeric::signbit(x);
      55             : }
      56             : } // namespace detail
      57             : 
      58             : constexpr auto isposinf =
      59             :     overloaded{special_value_args<>,
      60          21 :                [](const auto x) {
      61             :                  using detail::isposinf;
      62          21 :                  return isposinf(x);
      63             :                },
      64          17 :                [](const units::Unit &) { return units::none; }};
      65             : 
      66             : constexpr auto isneginf =
      67             :     overloaded{special_value_args<>,
      68          21 :                [](const auto x) {
      69             :                  using detail::isneginf;
      70          21 :                  return isneginf(x);
      71             :                },
      72          17 :                [](const units::Unit &) { return units::none; }};
      73             : 
      74             : constexpr auto replace_special = overloaded{
      75             :     arg_list<double, float>, transform_flags::expect_all_or_none_have_variance,
      76             :     transform_flags::force_variance_broadcast,
      77           5 :     [](const units::Unit &x, const units::Unit &repl) {
      78           5 :       expect::equals(x, repl);
      79           5 :       return x;
      80             :     }};
      81             : 
      82             : constexpr auto replace_special_out_arg = overloaded{
      83             :     arg_list<double, float>, transform_flags::expect_all_or_none_have_variance,
      84             :     transform_flags::force_variance_broadcast,
      85          16 :     [](units::Unit &a, const units::Unit &b, const units::Unit &repl) {
      86          16 :       expect::equals(b, repl);
      87          16 :       a = b;
      88          16 :     }};
      89             : 
      90             : constexpr auto nan_to_num =
      91           6 :     overloaded{replace_special, [](const auto x, const auto &repl) {
      92             :                  using std::isnan;
      93           6 :                  return isnan(x) ? repl : x;
      94             :                }};
      95             : 
      96             : constexpr auto nan_to_num_out_arg = overloaded{
      97          16 :     replace_special_out_arg, [](auto &x, const auto y, const auto &repl) {
      98             :       using numeric::isnan;
      99          16 :       x = isnan(y) ? repl : y;
     100          16 :     }};
     101             : 
     102             : constexpr auto positive_inf_to_num =
     103           3 :     overloaded{replace_special, [](const auto &x, const auto &repl) {
     104             :                  if constexpr (is_ValueAndVariance_v<std::decay_t<decltype(x)>>)
     105           0 :                    return isinf(x) && x.value > 0 ? repl : x;
     106             :                  else
     107           3 :                    return numeric::isinf(x) && x > 0 ? repl : x;
     108             :                }};
     109             : 
     110             : constexpr auto positive_inf_to_num_out_arg = overloaded{
     111          10 :     replace_special_out_arg, [](auto &x, const auto &y, const auto &repl) {
     112             :       if constexpr (is_ValueAndVariance_v<std::decay_t<decltype(y)>>)
     113           0 :         x = isinf(y) && y.value > 0 ? repl : y;
     114             :       else
     115          10 :         x = numeric::isinf(y) && y > 0 ? repl : y;
     116          10 :     }};
     117             : 
     118             : constexpr auto negative_inf_to_num =
     119           3 :     overloaded{replace_special, [](const auto &x, const auto &repl) {
     120             :                  if constexpr (is_ValueAndVariance_v<std::decay_t<decltype(x)>>)
     121           0 :                    return isinf(x) && x.value < 0 ? repl : x;
     122             :                  else
     123           3 :                    return numeric::isinf(x) && x < 0 ? repl : x;
     124             :                }};
     125             : 
     126             : constexpr auto negative_inf_to_num_out_arg = overloaded{
     127          10 :     replace_special_out_arg, [](auto &x, const auto &y, const auto &repl) {
     128             :       if constexpr (is_ValueAndVariance_v<std::decay_t<decltype(y)>>)
     129           0 :         x = isinf(y) && y.value < 0 ? repl : y;
     130             :       else
     131          10 :         x = numeric::isinf(y) && y < 0 ? repl : y;
     132          10 :     }};
     133             : 
     134             : } // namespace scipp::core::element

Generated by: LCOV version 1.14