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