Line data Source code
1 : #pragma once
2 :
3 : #include "functions/Abs.hpp"
4 :
5 : #include <thrust/transform.h>
6 : #include <thrust/extrema.h>
7 : #include <type_traits>
8 :
9 : namespace elsa
10 : {
11 : namespace detail
12 : {
13 : struct CwiseMaxFn {
14 : template <class T, class U>
15 : __host__ __device__ auto operator()(const T& lhs, const U& rhs) const noexcept
16 : -> std::common_type_t<T, U>
17 107 : {
18 107 : using data_t = std::common_type_t<T, U>;
19 107 : return thrust::max(static_cast<data_t>(lhs), static_cast<data_t>(rhs));
20 107 : }
21 :
22 : template <class T, class U>
23 : __host__ __device__ auto operator()(const thrust::complex<T>& lhs,
24 : const U& rhs) const noexcept
25 : -> std::common_type_t<T, U>
26 99 : {
27 99 : using data_t = std::common_type_t<T, U>;
28 99 : return thrust::max(static_cast<data_t>(elsa::abs(lhs)), static_cast<data_t>(rhs));
29 99 : }
30 :
31 : template <class T, class U>
32 : __host__ __device__ auto operator()(const T& lhs,
33 : const thrust::complex<U>& rhs) const noexcept
34 : -> std::common_type_t<T, U>
35 92 : {
36 92 : using data_t = std::common_type_t<T, U>;
37 92 : return thrust::max(static_cast<data_t>(lhs), static_cast<data_t>(elsa::abs(rhs)));
38 92 : }
39 :
40 : template <class T, class U>
41 : __host__ __device__ auto operator()(const thrust::complex<T>& lhs,
42 : const thrust::complex<U>& rhs) const noexcept
43 : -> std::common_type_t<T, U>
44 110 : {
45 110 : using data_t = std::common_type_t<T, U>;
46 110 : return thrust::max(static_cast<data_t>(elsa::abs(lhs)),
47 110 : static_cast<data_t>(elsa::abs(rhs)));
48 110 : }
49 : };
50 :
51 : struct CwiseMinFn {
52 : template <class T, class U>
53 : __host__ __device__ auto operator()(const T& lhs, const U& rhs) const noexcept
54 : -> std::common_type_t<T, U>
55 0 : {
56 0 : using data_t = std::common_type_t<T, U>;
57 0 : return thrust::min(static_cast<data_t>(lhs), static_cast<data_t>(rhs));
58 0 : }
59 :
60 : template <class T, class U>
61 : __host__ __device__ auto operator()(const thrust::complex<T>& lhs,
62 : const U& rhs) const noexcept
63 : -> std::common_type_t<T, U>
64 0 : {
65 0 : using data_t = std::common_type_t<T, U>;
66 0 : return thrust::min(static_cast<data_t>(elsa::abs(lhs)), static_cast<data_t>(rhs));
67 0 : }
68 :
69 : template <class T, class U>
70 : __host__ __device__ auto operator()(const T& lhs,
71 : const thrust::complex<U>& rhs) const noexcept
72 : -> std::common_type_t<T, U>
73 0 : {
74 0 : using data_t = std::common_type_t<T, U>;
75 0 : return thrust::min<data_t>(lhs, elsa::abs(rhs));
76 0 : }
77 :
78 : template <class T, class U>
79 : __host__ __device__ auto operator()(const thrust::complex<T>& lhs,
80 : const thrust::complex<U>& rhs) const noexcept
81 : -> std::common_type_t<T, U>
82 0 : {
83 0 : using data_t = std::common_type_t<T, U>;
84 0 : return thrust::min<data_t>(elsa::abs(lhs), elsa::abs(rhs));
85 0 : }
86 : };
87 :
88 : struct TernaryLess {
89 : template <class T, class U>
90 : __host__ __device__ auto operator()(const T& lhs, const U& rhs) const noexcept
91 : -> std::common_type_t<T, U>
92 68 : {
93 68 : using data_t = std::common_type_t<T, U>;
94 68 : return thrust::less{}(lhs, rhs) ? static_cast<data_t>(lhs)
95 68 : : static_cast<data_t>(rhs);
96 68 : }
97 :
98 : template <class T, class U>
99 : __host__ __device__ auto operator()(const thrust::complex<T>& lhs,
100 : const thrust::complex<U>& rhs) const noexcept
101 : -> thrust::complex<std::common_type_t<T, U>>
102 32 : {
103 32 : using data_t = std::common_type_t<T, U>;
104 32 : return thrust::less{}(static_cast<data_t>(elsa::abs(lhs)),
105 32 : static_cast<data_t>(elsa::abs(rhs)))
106 32 : ? lhs
107 32 : : rhs;
108 32 : }
109 : };
110 :
111 : struct TernaryGreater {
112 : template <class T, class U>
113 : __host__ __device__ auto operator()(const T& lhs, const U& rhs) const noexcept
114 : -> std::common_type_t<T, U>
115 11061 : {
116 11061 : using data_t = std::common_type_t<T, U>;
117 11061 : return thrust::greater{}(lhs, rhs) ? static_cast<data_t>(lhs)
118 11061 : : static_cast<data_t>(rhs);
119 11061 : }
120 :
121 : template <class T, class U>
122 : __host__ __device__ auto operator()(const thrust::complex<T>& lhs,
123 : const thrust::complex<U>& rhs) const noexcept
124 : -> thrust::complex<std::common_type_t<T, U>>
125 647 : {
126 647 : using data_t = std::common_type_t<T, U>;
127 647 : return thrust::greater{}(static_cast<data_t>(elsa::abs(lhs)),
128 647 : static_cast<data_t>(elsa::abs(rhs)))
129 696 : ? lhs
130 >1844*10^16 : : rhs;
131 647 : }
132 : };
133 :
134 : template <class Scalar>
135 : struct CwiseMinScalarFn {
136 : Scalar scalar_;
137 :
138 : template <class T>
139 : __host__ __device__ auto operator()(const T& val) const noexcept
140 106 : {
141 106 : return TernaryLess{}(val, scalar_);
142 106 : }
143 : };
144 :
145 : template <class Scalar>
146 : struct CwiseMaxScalarFn {
147 : Scalar scalar_;
148 :
149 : template <class T>
150 : __host__ __device__ auto operator()(const T& val) const noexcept
151 11746 : {
152 11746 : return TernaryGreater{}(val, scalar_);
153 11746 : }
154 : };
155 :
156 : } // namespace detail
157 :
158 : /// @brief Compute the coefficient wise maximum of two input ranges. For complex input's the
159 : /// absolute value of the complex number is used.
160 : /// @ingroup transforms
161 : template <class InputIter1, class InputIter2, class OutIter>
162 : void cwiseMax(InputIter1 xfirst, InputIter1 xlast, InputIter2 yfirst, OutIter out)
163 20 : {
164 20 : thrust::transform(xfirst, xlast, yfirst, out, detail::CwiseMaxFn{});
165 20 : }
166 :
167 : /// @brief Compute the coefficient wise minimum of two input ranges. For complex input's the
168 : /// absolute value of the complex number is used.
169 : /// @ingroup transforms
170 : template <class InputIter1, class InputIter2, class OutIter>
171 : void cwiseMin(InputIter1 xfirst, InputIter1 xlast, InputIter2 yfirst, OutIter out)
172 0 : {
173 0 : thrust::transform(xfirst, xlast, yfirst, out, detail::CwiseMinFn{});
174 0 : }
175 :
176 : /// @brief For each element in the vector set the element to the minimum of the element and the
177 : /// given scalar
178 : /// @ingroup transforms
179 : template <class InputIter1, class Scalar, class OutIter>
180 : void minimum(InputIter1 xfirst, InputIter1 xlast, Scalar scalar, OutIter out)
181 7 : {
182 7 : thrust::transform(xfirst, xlast, out, detail::CwiseMinScalarFn<Scalar>{scalar});
183 7 : }
184 :
185 : /// @brief For each element in the vector set the element to the maximum of the element and the
186 : /// given scalar
187 : /// @ingroup transforms
188 : template <class InputIter1, class Scalar, class OutIter>
189 : void maximum(InputIter1 xfirst, InputIter1 xlast, Scalar scalar, OutIter out)
190 178 : {
191 178 : thrust::transform(xfirst, xlast, out, detail::CwiseMaxScalarFn<Scalar>{scalar});
192 178 : }
193 : } // namespace elsa
|