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 <cstddef>
8 :
9 : #include "scipp/common/numeric.h"
10 : #include "scipp/common/overloaded.h"
11 : #include "scipp/core/eigen.h"
12 : #include "scipp/core/element/arg_list.h"
13 : #include "scipp/core/subbin_sizes.h"
14 : #include "scipp/core/time_point.h"
15 : #include "scipp/core/transform_common.h"
16 : #include "scipp/core/value_and_variance.h"
17 : #include "scipp/units/except.h"
18 : #include "scipp/units/unit.h"
19 :
20 : namespace scipp::core::element {
21 :
22 : /// Set the elements referenced by a span to 0
23 54594 : template <class T> void zero(const scipp::span<T> &data) {
24 189643 : for (auto &x : data)
25 135049 : x = 0.0;
26 54594 : }
27 :
28 : /// Set the elements references by the spans for values and variances to 0
29 : template <class T>
30 124 : void zero(const core::ValueAndVariance<scipp::span<T>> &data) {
31 124 : zero(data.value);
32 124 : zero(data.variance);
33 124 : }
34 :
35 : constexpr auto values = overloaded{
36 : transform_flags::no_out_variance, transform_flags::force_variance_broadcast,
37 1481 : core::element::arg_list<double, float>, [](const auto &x) {
38 : if constexpr (is_ValueAndVariance_v<std::decay_t<decltype(x)>>)
39 1194 : return x.value;
40 : else
41 287 : return x;
42 : }};
43 :
44 : constexpr auto variances =
45 : overloaded{transform_flags::no_out_variance,
46 : core::element::arg_list<double, float>,
47 : transform_flags::expect_variance_arg<0>,
48 : transform_flags::force_variance_broadcast,
49 17 : [](const auto &x) {
50 : if constexpr (is_ValueAndVariance_v<std::decay_t<decltype(x)>>)
51 17 : return x.variance;
52 : else
53 0 : return x; // unreachable but required for instantiation
54 : },
55 13 : [](const units::Unit &u) { return u * u; }};
56 :
57 : constexpr auto stddevs =
58 : overloaded{transform_flags::no_out_variance,
59 : core::element::arg_list<double, float>,
60 : transform_flags::expect_variance_arg<0>,
61 : transform_flags::force_variance_broadcast,
62 1009 : [](const auto &x) {
63 : using std::sqrt;
64 : if constexpr (is_ValueAndVariance_v<std::decay_t<decltype(x)>>)
65 1009 : return sqrt(x.variance);
66 : else
67 0 : return sqrt(x); // unreachable but required for instantiation
68 : },
69 103 : [](const units::Unit &u) { return u; }};
70 :
71 : constexpr auto issorted_common = overloaded{
72 : core::element::arg_list<
73 : std::tuple<bool, double, double>, std::tuple<bool, float, float>,
74 : std::tuple<bool, int64_t, int64_t>, std::tuple<bool, int32_t, int32_t>,
75 : std::tuple<bool, std::string, std::string>,
76 : std::tuple<bool, time_point, time_point>>,
77 : transform_flags::expect_no_variance_arg<1>,
78 : [](units::Unit &out, const units::Unit &left, const units::Unit &right) {
79 : core::expect::equals(left, right);
80 : out = units::none;
81 : }};
82 :
83 : constexpr auto issorted_nondescending = overloaded{
84 463155 : issorted_common, [](bool &out, const auto &left, const auto &right) {
85 463155 : out = out && (left <= right);
86 463155 : }};
87 :
88 : constexpr auto issorted_nonascending = overloaded{
89 1603 : issorted_common, [](bool &out, const auto &left, const auto &right) {
90 1603 : out = out && (left >= right);
91 1603 : }};
92 :
93 : constexpr auto islinspace =
94 : overloaded{arg_list<scipp::span<const double>, scipp::span<const float>,
95 : scipp::span<const int64_t>, scipp::span<const int32_t>,
96 : scipp::span<const time_point>>,
97 : transform_flags::expect_no_variance_arg<0>,
98 9686 : [](const units::Unit &) { return units::one; },
99 9711 : [](const auto &range) { return numeric::islinspace(range); }};
100 :
101 : constexpr auto isarange =
102 : overloaded{arg_list<scipp::span<const int64_t>, scipp::span<const int32_t>>,
103 : transform_flags::expect_no_variance_arg<0>,
104 4831 : [](const units::Unit &) { return units::one; },
105 4831 : [](const auto &range) { return numeric::isarange(range); }};
106 :
107 : constexpr auto zip =
108 : overloaded{arg_list<int64_t>, transform_flags::expect_no_variance_arg<0>,
109 : transform_flags::expect_no_variance_arg<1>,
110 248921 : [](const units::Unit &first, const units::Unit &second) {
111 248921 : expect::equals(first, second);
112 248921 : return first;
113 : },
114 18792787 : [](const auto first, const auto second) {
115 18792787 : return std::pair{first, second};
116 : }};
117 :
118 : template <int N>
119 : constexpr auto get = overloaded{arg_list<std::pair<scipp::index, scipp::index>>,
120 : transform_flags::expect_no_variance_arg<0>,
121 : [](const auto &x) { return std::get<N>(x); },
122 : [](const units::Unit &u) { return u; }};
123 :
124 : constexpr auto fill =
125 : overloaded{arg_list<double, float, std::tuple<float, double>>,
126 0 : [](auto &x, const auto &value) { x = value; }};
127 :
128 : constexpr auto fill_zeros =
129 : overloaded{arg_list<double, float, int64_t, int32_t, SubbinSizes>,
130 107680 : [](units::Unit &) {}, [](auto &x) { x = 0; }};
131 :
132 : template <class... Ts>
133 : constexpr arg_list_t<std::tuple<bool, Ts, Ts>...> where_arg_list{};
134 :
135 : constexpr auto where = overloaded{
136 : where_arg_list<double, float, int64_t, int32_t, bool, core::time_point,
137 : index_pair, std::string, Eigen::Vector3d, Eigen::Matrix3d,
138 : Eigen::Affine3d, core::Quaternion, core::Translation>,
139 : transform_flags::force_variance_broadcast,
140 91411 : [](const auto &condition, const auto &x, const auto &y) {
141 91411 : return condition ? x : y;
142 : },
143 2476 : [](const units::Unit &condition, const units::Unit &x,
144 : const units::Unit &y) {
145 2476 : expect::equals(units::none, condition);
146 2476 : expect::equals(x, y);
147 2476 : return x;
148 : }};
149 :
150 : } // namespace scipp::core::element
|