xtensor
Loading...
Searching...
No Matches
xcomplex.hpp
1/***************************************************************************
2 * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
3 * Copyright (c) QuantStack *
4 * *
5 * Distributed under the terms of the BSD 3-Clause License. *
6 * *
7 * The full license is in the file LICENSE, distributed with this software. *
8 ****************************************************************************/
9
10#ifndef XTENSOR_COMPLEX_HPP
11#define XTENSOR_COMPLEX_HPP
12
13#include <type_traits>
14#include <utility>
15
16#include <xtl/xcomplex.hpp>
17
18#include "xtensor/xbuilder.hpp"
19#include "xtensor/xexpression.hpp"
20#include "xtensor/xoffset_view.hpp"
21
22namespace xt
23{
24
31 /******************************
32 * real and imag declarations *
33 ******************************/
34
35 template <class E>
36 decltype(auto) real(E&& e) noexcept;
37
38 template <class E>
39 decltype(auto) imag(E&& e) noexcept;
40
41 /********************************
42 * real and imag implementation *
43 ********************************/
44
45 namespace detail
46 {
47 template <bool iscomplex = true>
48 struct complex_helper
49 {
50 template <class E>
51 inline static auto real(E&& e) noexcept
52 {
53 using real_type = typename std::decay_t<E>::value_type::value_type;
54 return xoffset_view<xclosure_t<E>, real_type, 0>(std::forward<E>(e));
55 }
56
57 template <class E>
58 inline static auto imag(E&& e) noexcept
59 {
60 using real_type = typename std::decay_t<E>::value_type::value_type;
61 return xoffset_view<xclosure_t<E>, real_type, sizeof(real_type)>(std::forward<E>(e));
62 }
63 };
64
65 template <>
66 struct complex_helper<false>
67 {
68 template <class E>
69 inline static decltype(auto) real(E&& e) noexcept
70 {
71 return std::forward<E>(e);
72 }
73
74 template <class E>
75 inline static auto imag(E&& e) noexcept
76 {
77 return zeros<typename std::decay_t<E>::value_type>(e.shape());
78 }
79 };
80
81 template <bool isexpression = true>
82 struct complex_expression_helper
83 {
84 template <class E>
85 inline static decltype(auto) real(E&& e) noexcept
86 {
87 return detail::complex_helper<xtl::is_complex<typename std::decay_t<E>::value_type>::value>::real(
88 std::forward<E>(e)
89 );
90 }
91
92 template <class E>
93 inline static decltype(auto) imag(E&& e) noexcept
94 {
95 return detail::complex_helper<xtl::is_complex<typename std::decay_t<E>::value_type>::value>::imag(
96 std::forward<E>(e)
97 );
98 }
99 };
100
101 template <>
102 struct complex_expression_helper<false>
103 {
104 template <class E>
105 inline static decltype(auto) real(E&& e) noexcept
106 {
107 return xtl::forward_real(std::forward<E>(e));
108 }
109
110 template <class E>
111 inline static decltype(auto) imag(E&& e) noexcept
112 {
113 return xtl::forward_imag(std::forward<E>(e));
114 }
115 };
116 }
117
127 template <class E>
128 inline decltype(auto) real(E&& e) noexcept
129 {
130 return detail::complex_expression_helper<is_xexpression<std::decay_t<E>>::value>::real(std::forward<E>(e
131 ));
132 }
133
143 template <class E>
144 inline decltype(auto) imag(E&& e) noexcept
145 {
146 return detail::complex_expression_helper<is_xexpression<std::decay_t<E>>::value>::imag(std::forward<E>(e
147 ));
148 }
149
150#define UNARY_COMPLEX_FUNCTOR(NS, NAME) \
151 struct NAME##_fun \
152 { \
153 template <class T> \
154 constexpr auto operator()(const T& t) const \
155 { \
156 using NS::NAME; \
157 return NAME(t); \
158 } \
159 \
160 template <class B> \
161 constexpr auto simd_apply(const B& t) const \
162 { \
163 using NS::NAME; \
164 return NAME(t); \
165 } \
166 }
167
168 namespace math
169 {
170 namespace detail
171 {
172 template <class T>
173 constexpr std::complex<T> conj_impl(const std::complex<T>& c)
174 {
175 return std::complex<T>(c.real(), -c.imag());
176 }
177
178 template <class T>
179 constexpr std::complex<T> conj_impl(const T& real)
180 {
181 return std::complex<T>(real, 0);
182 }
183
184#ifdef XTENSOR_USE_XSIMD
185 template <class T, class A>
186 xsimd::complex_batch_type_t<xsimd::batch<T, A>> conj_impl(const xsimd::batch<T, A>& z)
187 {
188 return xsimd::conj(z);
189 }
190#endif
191 }
192
193 UNARY_COMPLEX_FUNCTOR(std, norm);
194 UNARY_COMPLEX_FUNCTOR(std, arg);
195 UNARY_COMPLEX_FUNCTOR(detail, conj_impl);
196 }
197
198#undef UNARY_COMPLEX_FUNCTOR
199
206 template <class E>
207 inline auto conj(E&& e) noexcept
208 {
209 using functor = math::conj_impl_fun;
211 return type(functor(), std::forward<E>(e));
212 }
213
220 template <class E>
221 inline auto arg(E&& e) noexcept
222 {
223 using functor = math::arg_fun;
225 return type(functor(), std::forward<E>(e));
226 }
227
237 template <class E>
238 inline auto angle(E&& e, bool deg = false) noexcept
239 {
240 using value_type = xtl::complex_value_type_t<typename std::decay_t<E>::value_type>;
241 value_type multiplier = 1.0;
242 if (deg)
243 {
245 }
246 return arg(std::forward<E>(e)) * std::move(multiplier);
247 }
248
256 template <class E>
257 inline auto norm(E&& e) noexcept
258 {
259 using functor = math::norm_fun;
261 return type(functor(), std::forward<E>(e));
262 }
263}
264#endif
decltype(auto) imag(E &&e) noexcept
Return an xt::xexpression representing the imaginary part of the given expression.
Definition xcomplex.hpp:144
decltype(auto) real(E &&e) noexcept
Return an xt::xexpression representing the real part of the given expression.
Definition xcomplex.hpp:128
auto conj(E &&e) noexcept
Return an xt::xfunction evaluating to the complex conjugate of the given expression.
Definition xcomplex.hpp:207
auto arg(E &&e) noexcept
Calculates the phase angle (in radians) elementwise for the complex numbers in e.
Definition xcomplex.hpp:221
auto angle(E &&e, bool deg=false) noexcept
Calculates the phase angle elementwise for the complex numbers in e.
Definition xcomplex.hpp:238
auto norm(E &&e) noexcept
Calculates the squared magnitude elementwise for the complex numbers in e.
Definition xcomplex.hpp:257
standard mathematical functions for xexpressions