tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
complex.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2
3#ifndef TETL_COMPLEX_COMPLEX_HPP
4#define TETL_COMPLEX_COMPLEX_HPP
5
11#include <etl/_utility/move.hpp>
12
13namespace etl {
14
18template <typename T>
19struct complex {
20 using value_type = T;
21
22 constexpr complex(T const& re = T(), T const& im = T());
23 constexpr complex(complex const& other) = default;
24 template <typename X>
25 explicit(sizeof(X) > sizeof(T)) constexpr complex(complex<X> const& other);
26
27 constexpr auto operator=(T const& val) -> complex<T>&;
28 constexpr auto operator=(complex const& other) -> complex& = default;
29 template <typename X>
30 constexpr auto operator=(complex<X> const& other) -> complex<T>&;
31
32 [[nodiscard]] constexpr auto real() const -> T;
33 constexpr auto real(T val) -> void;
34
35 [[nodiscard]] constexpr auto imag() const -> T;
36 constexpr auto imag(T val) -> void;
37
38 constexpr auto operator+=(T const& val) -> complex<T>&;
39 constexpr auto operator-=(T const& val) -> complex<T>&;
40 constexpr auto operator*=(T const& val) -> complex<T>&;
41 constexpr auto operator/=(T const& val) -> complex<T>&;
42
43 template <typename X>
44 constexpr auto operator+=(complex<X> const& val) -> complex<T>&;
45 template <typename X>
46 constexpr auto operator-=(complex<X> const& val) -> complex<T>&;
47 template <typename X>
48 constexpr auto operator*=(complex<X> const& val) -> complex<T>&;
49 template <typename X>
50 constexpr auto operator/=(complex<X> const& val) -> complex<T>&;
51
52 template <size_t I, typename X>
53 friend constexpr auto get(complex<X>&) noexcept -> X&;
54
55 template <size_t I, typename X>
56 friend constexpr auto get(complex<X>&&) noexcept -> X&&;
57
58 template <size_t I, typename X>
59 friend constexpr auto get(complex<X> const&) noexcept -> X const&;
60
61 template <size_t I, typename X>
62 friend constexpr auto get(complex<X> const&&) noexcept -> X const&&;
63
64 friend constexpr auto operator==(complex const& lhs, complex const& rhs) -> bool
65 {
66 return lhs.real() == rhs.real() and lhs.imag() == rhs.imag();
67 }
68
69 friend constexpr auto operator==(complex const& lhs, T const& rhs) -> bool
70 {
71 return lhs.real() == rhs and lhs.imag() == T{};
72 }
73
74private:
75 value_type _real;
76 value_type _imag;
77};
78
79template <typename T>
80inline constexpr auto is_tuple_like<etl::complex<T>> = true;
81
82template <typename T>
83struct tuple_size<etl::complex<T>> : etl::integral_constant<etl::size_t, 2> { };
84
85template <size_t I, typename T>
86struct tuple_element<I, etl::complex<T>> {
87 static_assert(I < 2, "Index out of range for etl::complex");
88 using type = T;
89};
90
91template <size_t I, typename X>
92constexpr auto get(complex<X>& z) noexcept -> X&
93{
94 static_assert(I < 2, "Index out of range for etl::complex");
95 if constexpr (I == 0) {
96 return z._real;
97 } else {
98 return z._imag;
99 }
100}
101
102template <size_t I, typename X>
103constexpr auto get(complex<X>&& z) noexcept -> X&&
104{
105 static_assert(I < 2, "Index out of range for etl::complex");
106 if constexpr (I == 0) {
107 return etl::move(z._real);
108 } else {
109 return etl::move(z._imag);
110 }
111}
112
113template <size_t I, typename X>
114constexpr auto get(complex<X> const& z) noexcept -> X const&
115{
116 static_assert(I < 2, "Index out of range for etl::complex");
117 if constexpr (I == 0) {
118 return z._real;
119 } else {
120 return z._imag;
121 }
122}
123
124template <size_t I, typename X>
125constexpr auto get(complex<X> const&& z) noexcept -> X const&&
126{
127 static_assert(I < 2, "Index out of range for etl::complex");
128 if constexpr (I == 0) {
129 return etl::move(z._real);
130 } else {
131 return etl::move(z._imag);
132 }
133}
134
135template <typename T>
136constexpr complex<T>::complex(T const& re, T const& im)
137 : _real{re}
138 , _imag{im}
139{
140}
141
142template <typename T>
143template <typename X>
144constexpr complex<T>::complex(complex<X> const& other)
145 : _real{static_cast<T>(other.real())}
146 , _imag{static_cast<T>(other.imag())}
147{
148}
149
150template <typename T>
151constexpr auto complex<T>::real() const -> T
152{
153 return _real;
154}
155
156template <typename T>
157constexpr auto complex<T>::real(T const val) -> void
158{
159 _real = val;
160}
161
162template <typename T>
163constexpr auto complex<T>::imag() const -> T
164{
165 return _imag;
166}
167
168template <typename T>
169constexpr auto complex<T>::imag(T const val) -> void
170{
171 _imag = val;
172}
173
174template <typename T>
175constexpr auto complex<T>::operator=(T const& val) -> complex<T>&
176{
177 _real = val;
178 _imag = T{};
179 return *this;
180}
181
182template <typename T>
183constexpr auto complex<T>::operator+=(T const& val) -> complex<T>&
184{
185 _real += val;
186 return *this;
187}
188
189template <typename T>
190constexpr auto complex<T>::operator-=(T const& val) -> complex<T>&
191{
192 _real -= val;
193 return *this;
194}
195
196template <typename T>
197constexpr auto complex<T>::operator*=(T const& val) -> complex<T>&
198{
199 (*this) *= complex<T>{val};
200 return *this;
201}
202
203template <typename T>
204constexpr auto complex<T>::operator/=(T const& val) -> complex<T>&
205{
206 (*this) /= complex<T>{val};
207 return *this;
208}
209
210template <typename T>
211template <typename X>
212constexpr auto complex<T>::operator+=(complex<X> const& val) -> complex<T>&
213{
214 _real += val.real();
215 _imag += val.imag();
216 return *this;
217}
218
219template <typename T>
220template <typename X>
221constexpr auto complex<T>::operator-=(complex<X> const& val) -> complex<T>&
222{
223 _real -= val.real();
224 _imag -= val.imag();
225 return *this;
226}
227
228template <typename T>
229template <typename X>
230constexpr auto complex<T>::operator*=(complex<X> const& val) -> complex<T>&
231{
232 auto const r = static_cast<T>(_real * val.real() - _imag * val.imag());
233 _imag = static_cast<T>(_real * val.imag() + _imag * val.real());
234 _real = r;
235 return *this;
236}
237
238template <typename T>
239template <typename X>
240constexpr auto complex<T>::operator/=(complex<X> const& val) -> complex<T>&
241{
242 auto const norm = [](auto const& c) {
243 auto const x = c.real();
244 auto const y = c.imag();
245 return static_cast<T>(x * x + y * y);
246 };
247
248 auto const r = static_cast<T>(_real * val.real() + _imag * val.imag());
249 auto const n = norm(val);
250 _imag = (_imag * val.real() - _real * val.imag()) / n;
251 _real = r / n;
252 return *this;
253}
254
255template <typename T>
256constexpr auto operator+(complex<T> const& val) -> complex<T>
257{
258 return val;
259}
260
261template <typename T>
262constexpr auto operator-(complex<T> const& val) -> complex<T>
263{
264 return {static_cast<T>(-val.real()), static_cast<T>(-val.imag())};
265}
266
267template <typename T>
268[[nodiscard]] constexpr auto operator+(complex<T> const& lhs, complex<T> const& rhs) -> complex<T>
269{
270 return complex<T>(lhs) += rhs;
271}
272
273template <typename T>
274[[nodiscard]] constexpr auto operator+(complex<T> const& lhs, T const& rhs) -> complex<T>
275{
276 return complex<T>(lhs) += rhs;
277}
278
279template <typename T>
280[[nodiscard]] constexpr auto operator+(T const& lhs, complex<T> const& rhs) -> complex<T>
281{
282 return complex<T>(lhs) += rhs;
283}
284
285template <typename T>
286[[nodiscard]] constexpr auto operator-(complex<T> const& lhs, complex<T> const& rhs) -> complex<T>
287{
288 return complex<T>(lhs) -= rhs;
289}
290
291template <typename T>
292[[nodiscard]] constexpr auto operator-(complex<T> const& lhs, T const& rhs) -> complex<T>
293{
294 return complex<T>(lhs) -= rhs;
295}
296
297template <typename T>
298[[nodiscard]] constexpr auto operator-(T const& lhs, complex<T> const& rhs) -> complex<T>
299{
300 return complex<T>(lhs) -= rhs;
301}
302
303template <typename T>
304[[nodiscard]] constexpr auto operator*(complex<T> const& lhs, complex<T> const& rhs) -> complex<T>
305{
306 return complex<T>(lhs) *= rhs;
307}
308
309template <typename T>
310[[nodiscard]] constexpr auto operator*(complex<T> const& lhs, T const& rhs) -> complex<T>
311{
312 return complex<T>(lhs) *= rhs;
313}
314
315template <typename T>
316[[nodiscard]] constexpr auto operator*(T const& lhs, complex<T> const& rhs) -> complex<T>
317{
318 return complex<T>(lhs) *= rhs;
319}
320
321template <typename T>
322[[nodiscard]] constexpr auto operator/(complex<T> const& lhs, complex<T> const& rhs) -> complex<T>
323{
324 return complex<T>(lhs) /= rhs;
325}
326
327template <typename T>
328[[nodiscard]] constexpr auto operator/(complex<T> const& lhs, T const& rhs) -> complex<T>
329{
330 return complex<T>(lhs) /= rhs;
331}
332
333template <typename T>
334[[nodiscard]] constexpr auto operator/(T const& lhs, complex<T> const& rhs) -> complex<T>
335{
336 return complex<T>(lhs) /= rhs;
337}
338
339// NOLINTNEXTLINE(modernize-concat-nested-namespaces)
340inline namespace literals {
341inline namespace complex_literals {
342
343constexpr auto operator""_il(long double d) -> complex<long double> { return {0.0L, static_cast<long double>(d)}; }
344
345constexpr auto operator""_il(unsigned long long d) -> complex<long double>
346{
347 return {0.0L, static_cast<long double>(d)};
348}
349
350constexpr auto operator""_i(long double d) -> complex<double> { return {0.0, static_cast<double>(d)}; }
351
352constexpr auto operator""_i(unsigned long long d) -> complex<double> { return {0.0, static_cast<double>(d)}; }
353
354constexpr auto operator""_if(long double d) -> complex<float> { return {0.0F, static_cast<float>(d)}; }
355
356constexpr auto operator""_if(unsigned long long d) -> complex<float> { return {0.0F, static_cast<float>(d)}; }
357
358} // namespace complex_literals
359} // namespace literals
360
361} // namespace etl
362
363#endif // TETL_COMPLEX_COMPLEX_HPP
constexpr auto move(InputIt first, InputIt last, OutputIt destination) -> OutputIt
Moves the elements in the range [first, last), to another range beginning at destination,...
Definition move.hpp:26
constexpr auto norm(complex< T > const &z) noexcept -> T
Definition norm.hpp:14
constexpr auto real(complex< T > const &z) noexcept(noexcept(z.real())) -> T
Definition real.hpp:14
constexpr auto imag(complex< T > const &z) noexcept(noexcept(z.imag())) -> T
Definition imag.hpp:14
Definition complex.hpp:341
Definition adjacent_find.hpp:8
constexpr auto is_tuple_like
Definition is_tuple_like.hpp:9
constexpr auto get(complex< X > &z) noexcept -> X &
Definition complex.hpp:92
constexpr auto operator-(complex< T > const &val) -> complex< T >
Definition complex.hpp:262
constexpr auto operator+(complex< T > const &val) -> complex< T >
Definition complex.hpp:256
constexpr auto operator/(complex< T > const &lhs, complex< T > const &rhs) -> complex< T >
Definition complex.hpp:322
constexpr auto operator*(complex< T > const &lhs, complex< T > const &rhs) -> complex< T >
Definition complex.hpp:304
A complex number.
Definition complex.hpp:19
constexpr auto operator/=(T const &val) -> complex< T > &
Definition complex.hpp:204
friend constexpr auto get(complex< X > &) noexcept -> X &
Definition complex.hpp:92
constexpr auto operator-=(T const &val) -> complex< T > &
Definition complex.hpp:190
constexpr auto imag() const -> T
Definition complex.hpp:163
constexpr complex(T const &re=T(), T const &im=T())
Definition complex.hpp:136
friend constexpr auto operator==(complex const &lhs, T const &rhs) -> bool
Definition complex.hpp:69
constexpr auto operator=(complex< X > const &other) -> complex< T > &
constexpr auto operator=(T const &val) -> complex< T > &
Definition complex.hpp:175
constexpr auto operator+=(T const &val) -> complex< T > &
Definition complex.hpp:183
constexpr auto real() const -> T
Definition complex.hpp:151
constexpr auto operator*=(T const &val) -> complex< T > &
Definition complex.hpp:197
constexpr complex(complex const &other)=default
constexpr auto operator=(complex const &other) -> complex &=default
T value_type
Definition complex.hpp:20
Definition integral_constant.hpp:9
Provides compile-time indexed access to the type of the elements of the array using tuple-like interf...
Definition array.hpp:267
Definition tuple_size.hpp:15