Explicitly include a boost "windows" folder even on linux
[supercollider.git] / include / plugin_interface / SC_Complex.h
blobc8f8f712ebb58e320807f18de740691568b4d86c
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #ifndef _SC_Complex_
23 #define _SC_Complex_
25 #include <cmath>
27 #include "SC_Types.h"
28 #include "SC_Constants.h"
29 #include "float.h"
31 #ifdef _MSC_VER
32 // hypotf is c99, but not c++
33 #define hypotf _hypotf
34 #endif
36 ////////////////////////////////////////////////////////////////////////////////
38 namespace detail {
40 const int kSineSize = 8192;
41 const int kSineMask = kSineSize - 1;
42 const double kSinePhaseScale = kSineSize / twopi;
43 const int32 kPolarLUTSize = 2049;
44 const int32 kPolarLUTSize2 = kPolarLUTSize >> 1;
47 /* each object file that is including this header will have separate lookup tables */
48 namespace {
50 float gMagLUT[kPolarLUTSize];
51 float gPhaseLUT[kPolarLUTSize];
52 float gSine[kSineSize+1];
54 static bool initTables(void)
56 double sineIndexToPhase = twopi / kSineSize;
57 double pmf = (1L << 29) / twopi;
58 for (int i=0; i <= kSineSize; ++i) {
59 double phase = i * sineIndexToPhase;
60 float32 d = sin(phase);
61 gSine[i] = d;
64 double rPolarLUTSize2 = 1. / kPolarLUTSize2;
65 for (int i=0; i < kPolarLUTSize; ++i) {
66 double slope = (i - kPolarLUTSize2) * rPolarLUTSize2;
67 double angle = atan(slope);
68 gPhaseLUT[i] = (float)angle;
69 gMagLUT[i] = (float)(1.f / cos(angle));
72 return true;
75 bool dummy = initTables();
79 struct Polar;
82 struct Complex
84 Complex() {}
85 Complex(float r, float i) : real(r), imag(i) {}
86 void Set(float r, float i) { real = r; imag = i; }
88 Complex& operator=(Complex b) { real = b.real; imag = b.imag; return *this; }
89 Complex& operator=(float b) { real = b; imag = 0.; return *this; }
91 Polar ToPolar();
93 /**
94 * Converts cartesian to polar representation, using lookup tables.
95 * Note: in this implementation the phase values returned lie in the range [-pi/4, 7pi/4]
96 * rather than the more conventional [0, 2pi] or [-pi, pi].
98 Polar ToPolarApx();
100 void ToPolarInPlace();
102 void ToPolarApxInPlace();
104 float real, imag;
107 struct Polar
109 Polar() {}
110 Polar(float m, float p) : mag(m), phase(p) {}
111 void Set(float m, float p) { mag = m; phase = p; }
113 Complex ToComplex()
115 return Complex(mag * std::cos(phase), mag * std::sin(phase));
118 Complex ToComplexApx()
120 uint32 sinindex = (int32)(kSinePhaseScale * phase) & kSineMask;
121 uint32 cosindex = (sinindex + (kSineSize>>2)) & kSineMask;
122 return Complex(mag * gSine[cosindex], mag * gSine[sinindex]);
125 void ToComplexInPlace()
127 Complex complx = ToComplex();
128 mag = complx.real;
129 phase = complx.imag;
132 void ToComplexApxInPlace()
134 Complex complx = ToComplexApx();
135 mag = complx.real;
136 phase = complx.imag;
139 float mag, phase;
142 inline Polar Complex::ToPolar()
144 return Polar(hypotf(imag, real), std::atan2(imag, real));
147 inline Polar Complex::ToPolarApx()
149 int32 index;
150 float absreal = fabs(real);
151 float absimag = fabs(imag);
152 float mag, phase, slope;
153 if (absreal > absimag) {
154 slope = imag/real;
155 index = (int32)(kPolarLUTSize2 + kPolarLUTSize2 * slope);
156 mag = gMagLUT[index] * absreal;
157 phase = gPhaseLUT[index];
158 if (real > 0) {
159 return Polar(mag, phase);
160 } else {
161 return Polar(mag, (float)(pi + phase));
163 } else if (absimag > 0) {
164 slope = real/imag;
165 index = (int32)(kPolarLUTSize2 + kPolarLUTSize2 * slope);
166 mag = gMagLUT[index] * absimag;
167 phase = gPhaseLUT[index];
168 if (imag > 0) {
169 return Polar(mag, (float)(pi2 - phase));
170 } else {
171 return Polar(mag, (float)(pi32 - phase));
173 } else return Polar(0, 0);
176 inline void Complex::ToPolarInPlace()
178 Polar polar = ToPolar();
179 real = polar.mag;
180 imag = polar.phase;
183 inline void Complex::ToPolarApxInPlace()
185 Polar polar = ToPolarApx();
186 real = polar.mag;
187 imag = polar.phase;
192 using detail::Polar;
193 using detail::Complex;
195 struct ComplexFT
197 float dc, nyq;
198 Complex complex[1];
201 struct PolarFT
203 float dc, nyq;
204 Polar polar[1];
207 void ToComplex(Polar in, Complex& out);
209 inline Complex operator+(Complex a, Complex b) { return Complex(a.real + b.real, a.imag + b.imag); }
210 inline Complex operator+(Complex a, float b) { return Complex(a.real + b, a.imag); }
211 inline Complex operator+(float a, Complex b) { return Complex(a + b.real, b.imag); }
213 inline Complex& operator+=(Complex& a, const Complex& b) { a.real += b.real, a.imag += b.imag; return a; }
214 inline Complex& operator+=(Complex& a, float b) { a.real += b; return a; }
216 inline Complex operator-(Complex a, Complex b) { return Complex(a.real - b.real, a.imag - b.imag); }
217 inline Complex operator-(Complex a, float b) { return Complex(a.real - b, a.imag); }
218 inline Complex operator-(float a, Complex b) { return Complex(a - b.real, b.imag); }
220 inline Complex operator-=(Complex a, Complex b) { a.real -= b.real, a.imag -= b.imag; return a; }
221 inline Complex operator-=(Complex a, float b) { a.real -= b; return a; }
223 inline Complex operator*(Complex a, Complex b)
225 return Complex(a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real);
228 inline Complex operator*(Complex a, float b)
230 return Complex(a.real * b, a.imag * b);
233 inline Complex operator*(float a, Complex b)
235 return Complex(b.real * a, b.imag * a);
238 inline Complex operator*=(Complex a, Complex b)
240 a.Set(
241 a.real * b.real - a.imag * b.imag,
242 a.real * b.imag + a.imag * b.real
244 return a;
247 inline Complex operator*=(Complex a, float b)
249 a.real *= b;
250 a.imag *= b;
251 return a;
255 inline Polar operator*(Polar a, float b)
257 return Polar(a.mag * b, a.phase);
260 inline Polar operator*(float a, Polar b)
262 return Polar(a * b.mag, b.phase);
265 inline Polar operator*=(Polar a, float b)
267 a.mag *= b;
268 return a;
271 #endif