1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
|
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
|
3 | #pragma once
|
4 |
|
5 | #include "Prerequisites/BsPrerequisitesUtil.h"
|
6 |
|
7 | namespace bs
|
8 | {
|
9 | /** @addtogroup Math
|
10 | * @{
|
11 | */
|
12 |
|
13 | /** Complex numbers. */
|
14 | template <class Type>
|
15 | class Complex
|
16 | {
|
17 | public:
|
18 | Complex() = default;
|
19 |
|
20 | Complex(const Type& r, const Type& i)
|
21 | : mReal(r), mImag(i) {}
|
22 |
|
23 | Complex(const Complex& other)
|
24 | : mReal(other.real()), mImag(other.imag()) {}
|
25 |
|
26 | Complex<Type>& operator= (const Type& other)
|
27 | {
|
28 | mReal = other;
|
29 | mImag = Type();
|
30 |
|
31 | return *this;
|
32 | }
|
33 |
|
34 | Complex<Type>& operator+= (const Type& other)
|
35 | {
|
36 | mReal += other;
|
37 |
|
38 | return *this;
|
39 | }
|
40 |
|
41 | Complex<Type>& operator-= (const Type& other)
|
42 | {
|
43 | mReal -= other;
|
44 |
|
45 | return *this;
|
46 | }
|
47 |
|
48 | Complex<Type>& operator*= (const Type& other)
|
49 | {
|
50 | mReal *= other;
|
51 | mImag *= other;
|
52 |
|
53 | return *this;
|
54 | }
|
55 |
|
56 | Complex<Type>& operator/= (const Type& other)
|
57 | {
|
58 | mReal /= other;
|
59 | mImag /= other;
|
60 |
|
61 | return *this;
|
62 | }
|
63 |
|
64 | Complex<Type>& operator= (const Complex<Type>& other)
|
65 | {
|
66 | mReal = other.real();
|
67 | mImag = other.imag();
|
68 |
|
69 | return *this;
|
70 | }
|
71 |
|
72 | Complex<Type>& operator+= (const Complex<Type>& other)
|
73 | {
|
74 | mReal += other.real();
|
75 | mImag += other.imag();
|
76 |
|
77 | return *this;
|
78 | }
|
79 |
|
80 | Complex<Type>& operator-= (const Complex<Type>& other)
|
81 | {
|
82 | mReal -= other.real();
|
83 | mImag -= other.imag();
|
84 |
|
85 | return *this;
|
86 | }
|
87 |
|
88 | Complex<Type>& operator*= (const Complex<Type>& other)
|
89 | {
|
90 | const Type r = mReal * other.real() - mImag * other.imag();
|
91 | mImag = mReal * other.imag() + mImag * other.real();
|
92 | mReal = r;
|
93 |
|
94 | return *this;
|
95 | }
|
96 |
|
97 | Complex<Type>& operator/= (const Complex<Type>& other)
|
98 | {
|
99 | const Type r = mReal * other.real() + mImag * other.imag();
|
100 | const Type n = Complex::norm(other);
|
101 | mImag = (mImag * other.real() - mReal * other.imag()) / n;
|
102 | mReal = r / n;
|
103 |
|
104 | return *this;
|
105 | }
|
106 |
|
107 | Complex<Type> operator+ (const Type& other) const
|
108 | {
|
109 | return Complex(mReal + other, mImag);
|
110 | }
|
111 |
|
112 | Complex<Type> operator- (const Type& other) const
|
113 | {
|
114 | return Complex(mReal - other, mImag);
|
115 | }
|
116 |
|
117 | Complex<Type> operator* (const Type& other) const
|
118 | {
|
119 | return Complex(mReal * other, mImag);
|
120 | }
|
121 |
|
122 | Complex<Type> operator/ (const Type& other) const
|
123 | {
|
124 | return Complex(mReal / other, mImag);
|
125 | }
|
126 |
|
127 | Complex<Type> operator+ (const Complex<Type>& other) const
|
128 | {
|
129 | return Complex(mReal + other.real(), mImag + other.imag());
|
130 | }
|
131 |
|
132 | Complex<Type> operator- (const Complex<Type>& other) const
|
133 | {
|
134 | return Complex(mReal - other.real(), mImag - other.imag());
|
135 | }
|
136 |
|
137 | Complex<Type> operator* (const Complex<Type>& other) const
|
138 | {
|
139 | Complex<Type> res = *this;
|
140 |
|
141 | res *= other;
|
142 |
|
143 | return res;
|
144 | }
|
145 |
|
146 | Complex<Type> operator/ (const Complex<Type>& other) const
|
147 | {
|
148 | Complex<Type> res = *this;
|
149 |
|
150 | res /= other;
|
151 |
|
152 | return res;
|
153 | }
|
154 |
|
155 | bool operator== (const Complex<Type>& other) const
|
156 | {
|
157 | return mReal == other.real() && mImag == other.imag();
|
158 | }
|
159 |
|
160 | bool operator== (const Type& other) const
|
161 | {
|
162 | return mReal == other && mImag == Type();
|
163 | }
|
164 |
|
165 | bool operator!= (const Complex<Type>& other) const
|
166 | {
|
167 | return mReal != other.real() || mImag != other.imag();
|
168 | }
|
169 |
|
170 | bool operator!= (const Type& other) const
|
171 | {
|
172 | return mReal != other || mImag != Type();
|
173 | }
|
174 |
|
175 | Type& real() { return mReal; }
|
176 | Type& imag() { return mImag; }
|
177 |
|
178 | const Type& real() const { return mReal; }
|
179 | const Type& imag() const { return mImag; }
|
180 |
|
181 | static Type abs(const Complex<Type>& other)
|
182 | {
|
183 | Type x = other.real();
|
184 | Type y = other.imag();
|
185 | const Type s = std::max(std::abs(x), std::abs(y));
|
186 | if (s == Type())
|
187 | return s;
|
188 |
|
189 | x /= s;
|
190 | y /= s;
|
191 |
|
192 | return s * std::sqrt(x * x + y * y);
|
193 | }
|
194 |
|
195 | static Type arg(const Complex<Type>& other)
|
196 | {
|
197 | return std::atan2(other.imag(), other.real());
|
198 | }
|
199 |
|
200 | static Type norm(const Complex<Type>& other)
|
201 | {
|
202 | const Type x = other.real();
|
203 | const Type y = other.imag();
|
204 |
|
205 | return x * x + y * y;
|
206 | }
|
207 |
|
208 | static Complex<Type> conj(const Complex<Type>& other)
|
209 | {
|
210 | return Complex(other.real(), -other.imag());
|
211 | }
|
212 |
|
213 | static Complex<Type> polar(const Type& r, const Type& t = 0)
|
214 | {
|
215 | return Complex(r * std::cos(t), r * std::sin(t));
|
216 | }
|
217 |
|
218 | static Complex<Type> cos(const Complex<Type>& other)
|
219 | {
|
220 | const Type x = other.real();
|
221 | const Type y = other.imag();
|
222 |
|
223 | return Complex(std::cos(x) * std::cosh(y), -std::sin(x) * std::sinh(y));
|
224 | }
|
225 |
|
226 | static Complex<Type> cosh(const Complex<Type>& other)
|
227 | {
|
228 | const Type x = other.real();
|
229 | const Type y = other.imag();
|
230 |
|
231 | return Complex(std::cosh(x) * std::cos(y), std::sinh(x) * std::sin(y));
|
232 | }
|
233 |
|
234 | static Complex<Type> exp(const Complex<Type>& other)
|
235 | {
|
236 | return Complex::polar(std::exp(other.real()), other.imag());
|
237 | }
|
238 |
|
239 | static Complex<Type> log(const Complex<Type>& other)
|
240 | {
|
241 | return Complex(std::log(Complex::abs(other)), Complex::arg(other));
|
242 | }
|
243 |
|
244 | static Complex<Type> log10(const Complex<Type>& other)
|
245 | {
|
246 | return Complex::log(other) / std::log(Type(10));
|
247 | }
|
248 |
|
249 | static Complex<Type> pow(const Complex<Type>& other, const Type& i)
|
250 | {
|
251 | if (other.imag() == Type() && other.real() > Type())
|
252 | return Complex(std::pow(other.real(), i), other.imag());
|
253 |
|
254 | Complex<Type> t = Complex::log(other);
|
255 | return Complex::polar(std::exp(i * t.real()), i * t.imag());
|
256 | }
|
257 |
|
258 | static Complex<Type> pow(const Complex<Type>& x, const Complex<Type>& y)
|
259 | {
|
260 | return Complex::exp(y * Complex::log(x));
|
261 | }
|
262 |
|
263 | static Complex<Type> pow(const Type& i, const Complex<Type>& other)
|
264 | {
|
265 | return i > Type() ?
|
266 | Complex::polar(std::pow(i, other.real()), other.imag() * std::log(i))
|
267 | : Complex::pow(Complex(i, Type()), other);
|
268 | }
|
269 |
|
270 | static Complex<Type> sin(const Complex<Type>& other)
|
271 | {
|
272 | const Type x = other.real();
|
273 | const Type y = other.imag();
|
274 |
|
275 | return Complex(std::sin(x) * std::cosh(y), std::cos(x) * std::sinh(y));
|
276 | }
|
277 |
|
278 | static Complex<Type> sinh(const Complex<Type>& other)
|
279 | {
|
280 | const Type x = other.real();
|
281 | const Type y = other.imag();
|
282 |
|
283 | return Complex(std::sinh(x) * std::cos(y), std::cosh(x) * std::sin(y));
|
284 | }
|
285 |
|
286 | static Complex<Type> sqrt(const Complex<Type>& other)
|
287 | {
|
288 | const Type x = other.real();
|
289 | const Type y = other.imag();
|
290 |
|
291 | if (x == Type())
|
292 | {
|
293 | Type t = std::sqrt(std::abs(y) / 2);
|
294 | return Complex(t, y < Type() ? -t : t);
|
295 | }
|
296 | else
|
297 | {
|
298 | Type t = std::sqrt(2 * (Complex::abs(other) + std::abs(x)));
|
299 | Type u = t / 2;
|
300 | return x > Type() ? Complex(u, y / t)
|
301 | : Complex(std::abs(y) / t, y < Type() ? -u : u);
|
302 | }
|
303 | }
|
304 |
|
305 | static Complex<Type> tan(const Complex<Type>& other)
|
306 | {
|
307 | return Complex::sin(other) / Complex::cos(other);
|
308 | }
|
309 |
|
310 | static Complex<Type> tanh(const Complex<Type>& other)
|
311 | {
|
312 | return Complex::sinh(other) / Complex::cosh(other);
|
313 | }
|
314 |
|
315 | friend std::ostream& operator<< (std::ostream& os, const Complex<Type> other)
|
316 | {
|
317 | return os << other.real() << ", " << other.imag();
|
318 | }
|
319 |
|
320 | private:
|
321 | Type mReal;
|
322 | Type mImag;
|
323 | };
|
324 |
|
325 | /** @} */
|
326 | }
|
327 | |