Allolib  1.0
C++ Components For Interactive Multimedia
al_Complex.hpp
1 #ifndef INCLUDE_AL_COMPLEX_HPP
2 #define INCLUDE_AL_COMPLEX_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
8  Copyright (C) 2012. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are met:
13 
14  Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16 
17  Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 
21  Neither the name of the University of California nor the names of its
22  contributors may be used to endorse or promote products derived from
23  this software without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  POSSIBILITY OF SUCH DAMAGE.
36 
37 
38  File description:
39  Complex number class
40 
41  File author(s):
42  Lance Putnam, 2006, putnam.lance@gmail.com
43 */
44 
45 #include <cmath>
46 #include "al/math/al_Constants.hpp"
47 
48 namespace al {
49 
50 template <class T>
51 class Complex;
52 template <class T>
53 class Polar;
54 
55 typedef Polar<float> Polarf;
56 typedef Polar<double> Polard;
57 typedef Complex<float> Complexf;
58 typedef Complex<double> Complexd;
59 
63 template <class T>
64 class Polar {
65  public:
66  union {
67  struct {
68  T m;
69  T p;
70  };
71  T elems[2];
72  };
73 
75  Polar(const T& phs = T(0)) : m(T(1)), p(phs) {}
76 
79  Polar(const T& mag, const T& phs) : m(mag), p(phs) {}
80 
82  Polar(const Complex<T>& v) { *this = v; }
83 
84  Polar& operator=(const Complex<T>& v) {
85  m = v.norm();
86  p = v.arg();
87  return *this;
88  }
89 };
90 
94 template <class T>
95 class Complex {
96  public:
97  typedef Complex<T> C;
98 
99  union {
100  struct {
101  T r;
102  T i;
103  };
104  T elems[2];
105  };
106 
107  Complex(const Complex& v) : r(v.r), i(v.i) {}
108  Complex(const Polar<T>& v) { *this = v; }
109  Complex(const T& r = T(0), const T& i = T(0)) : r(r), i(i) {}
110  Complex(const T& m, const T& p, int fromPolar) { (*this) = Polar<T>(m, p); }
111 
112  C& arg(T v) {
113  return fromPolar(norm(), v);
114  }
115  C& norm(T v) {
116  return fromPolar(v, arg());
117  }
118 
120  r = ::cos(phase);
121  i = ::sin(phase);
122  return *this;
123  }
124  C& fromPolar(T m, T p) {
125  return set(Polar<T>(m, p));
126  }
127 
129  C& set(T vr, T vi) {
130  r = vr;
131  i = vi;
132  return *this;
133  }
134  C& set(const Polar<T>& p) { return *this = p; }
135 
136  T& operator[](int i) { return elems[i]; }
137  const T& operator[](int i) const { return elems[i]; }
138 
139  // Accessors compatible with std::complex
140  T& real() { return r; }
141  const T& real() const { return r; }
142  T& imag() { return i; }
143  const T& imag() const { return i; }
144 
145  bool operator==(const C& v) const {
146  return (r == v.r) && (i == v.i);
147  }
148  bool operator==(const T& v) const {
149  return (r == v) && (i == T(0));
150  }
151  bool operator!=(const C& v) const {
152  return (r != v.r) || (i != v.i);
153  }
154  bool operator>(const C& v) const {
155  return normSqr() > v.normSqr();
156  }
157  bool operator<(const C& c) const {
158  return normSqr() < c.normSqr();
159  }
160 
161  C& operator=(const Polar<T>& v) {
162  r = v.m * ::cos(v.p);
163  i = v.m * ::sin(v.p);
164  return *this;
165  }
166  C& operator=(const C& v) {
167  r = v.r;
168  i = v.i;
169  return *this;
170  }
171  C& operator=(T v) {
172  r = v;
173  i = T(0);
174  return *this;
175  }
176  C& operator-=(const C& v) {
177  r -= v.r;
178  i -= v.i;
179  return *this;
180  }
181  C& operator-=(T v) {
182  r -= v;
183  return *this;
184  }
185  C& operator+=(const C& v) {
186  r += v.r;
187  i += v.i;
188  return *this;
189  }
190  C& operator+=(T v) {
191  r += v;
192  return *this;
193  }
194  C& operator*=(const C& v) {
195  return set(r * v.r - i * v.i, i * v.r + r * v.i);
196  }
197  C& operator*=(T v) {
198  r *= v;
199  i *= v;
200  return *this;
201  }
202  C& operator/=(const C& v) { return (*this) *= v.recip(); }
203  C& operator/=(T v) {
204  r /= v;
205  i /= v;
206  return *this;
207  }
208 
209  C operator-() const { return C(-r, -i); }
210  C operator-(const C& v) const { return C(*this) -= v; }
211  C operator-(T v) const { return C(*this) -= v; }
212  C operator+(const C& v) const { return C(*this) += v; }
213  C operator+(T v) const { return C(*this) += v; }
214  C operator*(const C& v) const { return C(*this) *= v; }
215  C operator*(T v) const { return C(*this) *= v; }
216  C operator/(const C& v) const { return C(*this) /= v; }
217  C operator/(T v) const { return C(*this) /= v; }
218 
219  T arg() const { return atan2(i, r); }
220  T argUnit() const {
221  T r = arg() / (2 * M_PI);
222  return r > 0 ? r : r + 1;
223  }
224  C conj() const { return C(r, -i); }
225  T dot(const C& v) const {
226  return r * v.r + i * v.i;
227  }
228  C exp() const { return Polar<T>(::exp(r), i); }
229  C log() const {
230  return Complex<T>(T(0.5) * ::log(normSqr()), arg());
231  }
232  T norm() const { return ::sqrt(normSqr()); }
233  T normSqr() const { return dot(*this); }
234  C& normalize(T m = T(1)) {
235  return *this *= (m / norm());
236  }
237  C pow(const C& v) const {
238  return ((*this).log() * v).exp();
239  }
240  C pow(T v) const { return ((*this).log() * v).exp(); }
241  C recip() const {
242  return conj() / normSqr();
243  }
244  C sgn(T m = T(1)) const {
245  return C(*this).normalize(m);
246  }
247  C sqr() const { return C(r * r - i * i, T(2) * r * i); }
248 
250  C sqrt() const {
251  static const T c = T(1) / ::sqrt(T(2));
252  T n = norm();
253  T a = ::sqrt(n + r) * c;
254  T b = ::sqrt(n - r) * (i < T(0) ? -c : c);
255  return C(a, b);
256  }
257 
258  C cos() const {
259  return C(::cos(r) * ::cosh(i), -::sin(r) * ::sinh(i));
260  }
261  C sin() const {
262  return C(::sin(r) * ::cosh(i), ::cos(r) * ::sinh(i));
263  }
264  C cosh() const {
265  return C(::cos(i) * ::sinh(r), ::sin(i) * ::cosh(r));
266  }
267  C sinh() const {
268  return C(::cos(i) * ::cosh(r), ::sin(i) * ::sinh(r));
269  }
270 
271  T abs() const { return norm(); }
272  T mag() const { return norm(); }
273  T magSqr() const { return normSqr(); }
274  T phase() const { return arg(); }
275 };
276 
277 #define TEM \
278  template <class T> \
279  inline
280 TEM T abs(const Complex<T>& c) { return c.mag(); }
281 TEM Complex<T> exp(const Complex<T>& c) { return c.exp(); }
282 TEM Complex<T> log(const Complex<T>& c) { return c.log(); }
283 TEM Complex<T> pow(const Complex<T>& b, const Complex<T>& e) {
284  return b.pow(e);
285 }
286 TEM Complex<T> pow(const Complex<T>& b, const T& e) { return b.pow(e); }
287 // TEM Complex<T> sqrt(const Complex<T>& v){ return v.sqrt(); } // TODO: these
288 // ambiguate other functions TEM Complex<T> cos(const Complex<T>& v){ return
289 // v.cos(); } TEM Complex<T> sin(const Complex<T>& v){ return v.sin(); }
290 #undef TEM
291 
292 template <class T>
293 inline Complex<T> operator+(T r, const Complex<T>& c) {
294  return c + r;
295 }
296 
297 template <class T>
298 inline Complex<T> operator-(T r, const Complex<T>& c) {
299  return -c + r;
300 }
301 
302 template <class T>
303 inline Complex<T> operator*(T r, const Complex<T>& c) {
304  return c * r;
305 }
306 
307 template <class T>
308 inline Complex<T> operator/(T r, const Complex<T>& c) {
309  return c.conj() * (r / c.normSqr());
310 }
311 
312 template <class VecN, class T>
313 VecN rotate(const VecN& v, const VecN& p, const Complex<T>& a) {
314  return v * a.r + p * a.i;
315 }
316 
320 template <class VecN, class T>
321 void rotatePlane(VecN& v1, VecN& v2, const Complex<T>& a) {
322  VecN t = al::rotate(v1, v2, a);
323  v2 = al::rotate(v2, VecN(-v1), a);
324  v1 = t;
325 }
326 
330 template <class Vec3, class T>
331 Vec3 sterProj(const al::Complex<T>& c) {
332  T magSqr = c.magSqr();
333  T mul = T(2) / (magSqr + T(1));
334  return Vec3(c.r * mul, c.i * mul, (magSqr - T(1)) * mul * T(0.5));
335 }
336 
337 } // namespace al
338 
339 #endif
T phase() const
Returns argument (angle)
Definition: al_Complex.hpp:274
T arg() const
Returns argument in [-pi, pi].
Definition: al_Complex.hpp:219
C sin() const
Returns sin(z)
Definition: al_Complex.hpp:261
C sqrt() const
Returns square root.
Definition: al_Complex.hpp:250
C & set(T vr, T vi)
Set real and imaginary components.
Definition: al_Complex.hpp:129
C & fromPolar(T m, T p)
Set magnitude and phase.
Definition: al_Complex.hpp:124
C pow(const C &v) const
Returns z^v.
Definition: al_Complex.hpp:237
T abs() const
Returns norm (radius), |z|.
Definition: al_Complex.hpp:271
T norm() const
Returns norm (radius), |z|.
Definition: al_Complex.hpp:232
C exp() const
Returns e^z.
Definition: al_Complex.hpp:228
T i
Imaginary component.
Definition: al_Complex.hpp:102
T r
Real component.
Definition: al_Complex.hpp:101
bool operator<(const C &c) const
Returns true if norm is less than argument's norm.
Definition: al_Complex.hpp:157
C sinh() const
Returns sinh(z)
Definition: al_Complex.hpp:267
bool operator==(const T &v) const
Returns true if real and equals value.
Definition: al_Complex.hpp:148
C cosh() const
Returns cosh(z)
Definition: al_Complex.hpp:264
bool operator>(const C &v) const
Returns true if norm is greater than argument's norm.
Definition: al_Complex.hpp:154
T dot(const C &v) const
Returns vector dot product.
Definition: al_Complex.hpp:225
T normSqr() const
Returns square of norm, |z|^2.
Definition: al_Complex.hpp:233
C recip() const
Return multiplicative inverse, 1/z.
Definition: al_Complex.hpp:241
C cos() const
Returns cos(z)
Definition: al_Complex.hpp:258
T mag() const
Returns norm (radius), |z|.
Definition: al_Complex.hpp:272
C & norm(T v)
Set norm leaving argument the same.
Definition: al_Complex.hpp:115
bool operator!=(const C &v) const
Returns true if any components are not equal.
Definition: al_Complex.hpp:151
C & arg(T v)
Set argument leaving norm the same.
Definition: al_Complex.hpp:112
C sqr() const
Returns square.
Definition: al_Complex.hpp:247
bool operator==(const C &v) const
Returns true if all components are equal.
Definition: al_Complex.hpp:145
C conj() const
Returns conjugate, z*.
Definition: al_Complex.hpp:224
C & normalize(T m=T(1))
Sets magnitude to 1, |z|=1.
Definition: al_Complex.hpp:234
C & fromPolar(T phase)
Set phase and normalize.
Definition: al_Complex.hpp:119
C sgn(T m=T(1)) const
Returns signum, z/|z|, the closest point on unit circle.
Definition: al_Complex.hpp:244
T argUnit() const
Return argument in unit interval [0, 1)
Definition: al_Complex.hpp:220
C pow(T v) const
Returns z^v.
Definition: al_Complex.hpp:240
C log() const
Returns log(z)
Definition: al_Complex.hpp:229
T magSqr() const
Returns square of norm, |z|^2.
Definition: al_Complex.hpp:273
Polar(const T &mag, const T &phs)
Definition: al_Complex.hpp:79
Polar(const Complex< T > &v)
Definition: al_Complex.hpp:82
T p
Phase, in radians.
Definition: al_Complex.hpp:69
Polar(const T &phs=T(0))
Definition: al_Complex.hpp:75
T m
Magnitude.
Definition: al_Complex.hpp:68
Vec3 sterProj(const al::Complex< T > &c)
Definition: al_Complex.hpp:331
void rotatePlane(VecN &v1, VecN &v2, const Complex< T > &a)
Definition: al_Complex.hpp:321
Definition: al_App.hpp:23