cmake build system: visiblity support for clang
[supercollider.git] / SCClassLibrary / Common / Math / Complex.sc
blobbe4dc41ddfa8df30c07768ae6129987b99644c1f
1 Complex : Number {
2         var <>real, <>imag;
4         *new { arg real, imag;
5                 ^super.newCopyArgs(real, imag);
6         }
8         + { arg aNumber, adverb;
9                 if ( aNumber.isNumber, {
10                         ^Complex.new(real + aNumber.real, imag + aNumber.imag)
11                 },{
12                         ^aNumber.performBinaryOpOnComplex('+', this, adverb)
13                 });
14         }
15         - { arg aNumber, adverb;
16                 if ( aNumber.isNumber, {
17                         ^Complex.new(real - aNumber.real, imag - aNumber.imag)
18                 },{
19                         ^aNumber.performBinaryOpOnComplex('-', this, adverb)
20                 });
21         }
22         * { arg aNumber, adverb;
23                 if ( aNumber.isNumber, {
24                         ^Complex.new(
25                                 // these are implemented as additional message sends so that UGens can
26                                 // optimize the 6 operations down to 2 UGen instances.
27                                 (real * aNumber.real) - (imag * aNumber.imag),
28                                 (real * aNumber.imag) + (imag * aNumber.real)
29                         )
30                 },{
31                         ^aNumber.performBinaryOpOnComplex('*', this, adverb)
32                 });
33         }
34         / { arg aNumber, adverb;
35                 var denom, yr, yi;
36                 if ( aNumber.isNumber, {
37                         yr = aNumber.real;
38                         yi = aNumber.imag;
39                         denom = 1.0 / (yr * yr + (yi * yi));
40                         ^Complex.new(
41                                 ((real * yr) + (imag * yi)) * denom,
42                                 ((imag * yr) - (real * yi)) * denom)
43                 },{
44                         ^aNumber.performBinaryOpOnComplex('/', this, adverb)
45                 });
46         }
48         < { arg aNumber, adverb;
49                 if ( aNumber.isNumber, {
50                         ^real < aNumber.real
51                 },{
52                         ^aNumber.performBinaryOpOnComplex('<', this, adverb)
53                 });
54         }
56         == { arg aNumber, adverb;
57                 if ( aNumber.isNumber, {
58                         ^real == aNumber.real and: { imag == aNumber.imag }
59                 },{
60                         ^aNumber.performBinaryOpOnComplex('==', this, adverb)
61                 });
62         }
63         hash {
64                 ^real.hash bitXor: imag.hash
65         }
67         // double dispatch
68         performBinaryOpOnSimpleNumber { arg aSelector, aNumber, adverb;
69                 ^aNumber.asComplex.perform(aSelector, this, adverb)
70         }
71         performBinaryOpOnSignal { arg aSelector, aSignal, adverb;
72                 ^aSignal.asComplex.perform(aSelector, this)
73         }
74         performBinaryOpOnComplex { arg aSelector, aNumber, adverb;
75                 ^error("Math operation failed.\n")
76         }
77         performBinaryOpOnUGen { arg aSelector, aUGen, adverb;
78                 ^aUGen.asComplex.perform(aSelector, this, adverb)
79         }
81         neg { ^Complex.new(real.neg, imag.neg) }
82         conjugate { ^Complex.new(real, imag.neg) }
83         
84         squared { ^this * this }
85         cubed { ^this * this * this }
86         exp { ^exp(real) * Complex.new(cos(imag), sin(real)) }
87         
88         pow { arg aNumber; // return(this ** aNumber)
89                 
90                 // Notation below:
91                 // t=this, p=power, i=sqrt(-1)
92                 // Derivation:
93                 // t ** p = exp(p*log(t)) = ... = r*exp(i*a)
94                 
95                 var p_real, p_imag, t_mag, t_phase, t_maglog;
96                 var mag, phase;
97                 
98                 aNumber = aNumber.asComplex;
99                 
100                 p_real = aNumber.real;
101                 p_imag = aNumber.imag;
102                 if(p_real == 0.0 and: { p_imag == 0 }) { ^Complex(1.0, 0.0) };
103                 if(p_imag == 0.0 and: { imag == 0.0 } and: { real > 0.0 }) { 
104                         ^Complex(real ** p_real, 0.0) 
105                 };
106                 
107                 t_mag = this.magnitude;
108                 if(t_mag == 0.0) { ^Complex(0.0, 0.0) };
109                 t_maglog = 0.5 * log(t_mag);
110                 t_phase = this.phase;
111                 
112                 mag = exp((p_real * t_maglog) - (p_imag * t_phase));
113                 phase = (p_imag * t_maglog) + (p_real * t_phase);
114                 
115                 ^Complex(mag * cos(phase), mag * sin(phase))
116         }
117                 
118         magnitude { ^hypot(real, imag) }
119         abs { ^hypot(real, imag) }
120         rho { ^hypot(real, imag) }
122         magnitudeApx { ^hypotApx(real, imag) }
124         angle { ^atan2(imag, real) }
125         phase { ^atan2(imag, real) }
126         theta { ^atan2(imag, real) }
128         coerce { arg aNumber; ^aNumber.asComplex }
129         round { arg aNumber = 1.0; 
130                 ^Complex(real.round(aNumber), imag.round(aNumber))
131         }
133         asInteger { ^real.asInteger }
134         asFloat { ^real.asFloat }
136         asComplex { ^this }
137         asPolar { ^Polar.new(this.rho, this.theta) }
138         asPoint { ^Point.new(this.real, this.imag) }
140         printOn { arg stream;
141                 stream << "Complex( " << real << ", " << imag << " )";
142         }