001    // --- BEGIN LICENSE BLOCK ---
002    /* 
003     * Copyright (c) 2009, Mikio L. Braun
004     * All rights reserved.
005     * 
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions are
008     * met:
009     * 
010     *     * Redistributions of source code must retain the above copyright
011     *       notice, this list of conditions and the following disclaimer.
012     * 
013     *     * Redistributions in binary form must reproduce the above
014     *       copyright notice, this list of conditions and the following
015     *       disclaimer in the documentation and/or other materials provided
016     *       with the distribution.
017     * 
018     *     * Neither the name of the Technische Universit??t Berlin nor the
019     *       names of its contributors may be used to endorse or promote
020     *       products derived from this software without specific prior
021     *       written permission.
022     * 
023     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
024     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
025     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
026     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
027     * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
028     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
029     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
030     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
031     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
032     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
033     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
034     */
035    // --- END LICENSE BLOCK ---
036    
037    package org.jblas;
038    
039    import java.nio.FloatBuffer;
040    
041    /**
042     * A complex value with float precision.
043     * 
044     * @author Mikio L. Braun
045     * 
046     */
047    public class ComplexFloat {
048    
049        private float r,  i;
050        public static final ComplexFloat UNIT = new ComplexFloat(1.0f, 0.0f);
051        public static final ComplexFloat I = new ComplexFloat(0.0f, 1.0f);
052        public static final ComplexFloat NEG_UNIT = new ComplexFloat(-1.0f, 0.0f);
053        public static final ComplexFloat NEG_I = new ComplexFloat(0.0f, -1.0f);
054        public static final ComplexFloat ZERO = new ComplexFloat(0.0f);
055    
056        public ComplexFloat(float real, float imag) {
057            r = real;
058            i = imag;
059        }
060    
061        public ComplexFloat(float real) {
062            this(real, 0.0f);
063        }
064    
065        public String toString() {
066            if (i >= 0) {
067                return r + " + " + i + "i";
068            } else {
069                return r + " - " + (-i) + "i";
070            }
071        }
072    
073        public ComplexFloat set(float real, float imag) {
074            r = real;
075            i = imag;
076            return this;
077        }
078    
079        public float real() {
080            return r;
081        }
082    
083        public float imag() {
084            return i;
085        }
086    
087        public ComplexFloat dup() {
088            return new ComplexFloat(r, i);
089        }
090    
091        public ComplexFloat copy(ComplexFloat other) {
092            r = other.r;
093            i = other.i;
094            return this;
095        }
096    
097        /** Add two complex numbers in-place */
098        public ComplexFloat addi(ComplexFloat c, ComplexFloat result) {
099            if (this == result) {
100                r += c.r;
101                i += c.i;
102            } else {
103                result.r = r + c.r;
104                result.i = i + c.i;
105            }
106            return result;
107        }
108    
109        /** Add two complex numbers in-place storing the result in this. */
110        public ComplexFloat addi(ComplexFloat c) {
111            return addi(c, this);
112        }
113    
114        /** Add two complex numbers. */
115        public ComplexFloat add(ComplexFloat c) {
116            return dup().addi(c);
117        }
118    
119        /** Add a real number to a complex number in-place. */
120        public ComplexFloat addi(float a, ComplexFloat result) {
121            if (this == result) {
122                r += a;
123            } else {
124                result.r = r + a;
125                result.i = i;
126            }
127            return result;
128        }
129    
130        /** Add a real number to complex number in-place, storing the result in this. */
131        public ComplexFloat addi(float c) {
132            return addi(c, this);
133        }
134    
135        /** Add a real number to a complex number. */
136        public ComplexFloat add(float c) {
137            return dup().addi(c);
138        }
139    
140        /** Subtract two complex numbers, in-place */
141        public ComplexFloat subi(ComplexFloat c, ComplexFloat result) {
142            if (this == result) {
143                r -= c.r;
144                i -= c.i;
145            } else {
146                result.r = r - c.r;
147                result.i = i - c.i;
148            }
149            return this;
150        }
151        
152        public ComplexFloat subi(ComplexFloat c) {
153            return subi(c, this);
154        }
155    
156        /** Subtract two complex numbers */
157        public ComplexFloat sub(ComplexFloat c) {
158            return dup().subi(c);
159        }
160    
161        public ComplexFloat subi(float a, ComplexFloat result) {
162            if (this == result) {
163                r -= a;
164            } else {
165                result.r = r - a;
166                result.i = i;
167            }
168            return result;
169        }
170        
171        public ComplexFloat subi(float a) {
172            return subi(a, this);
173        }
174    
175        public ComplexFloat sub(float r) {
176            return dup().subi(r);
177        }
178    
179        /** Multiply two complex numbers, inplace */
180        public ComplexFloat muli(ComplexFloat c, ComplexFloat result) {
181            float newR = r * c.r - i * c.i;
182            float newI = r * c.i + i * c.r;
183            result.r = newR;
184            result.i = newI;
185            return result;
186        }
187        
188        public ComplexFloat muli(ComplexFloat c) {
189            return muli(c, this);
190        }
191    
192        /** Multiply two complex numbers */
193        public ComplexFloat mul(ComplexFloat c) {
194            return dup().muli(c);
195        }
196    
197        public ComplexFloat mul(float v) {
198            return dup().muli(v);
199        }
200    
201        public ComplexFloat muli(float v, ComplexFloat result) {
202            if (this == result) {
203                r *= v;
204                i *= v;    
205            } else {
206                result.r = r * v;
207                result.i = i * v;
208            }
209            return this;
210        }
211        
212        public ComplexFloat muli(float v) {
213            return muli(v, this);
214        }
215    
216        /** Divide two complex numbers */
217        public ComplexFloat div(ComplexFloat c) {
218            return dup().divi(c);
219        }
220    
221        /** Divide two complex numbers, in-place */
222        public ComplexFloat divi(ComplexFloat c, ComplexFloat result) {
223            float d = c.r * c.r + c.i * c.i;
224            float newR = (r * c.r + i * c.i) / d;
225            float newI = (i * c.r - r * c.i) / d;
226            result.r = newR;
227            result.i = newI;
228            return result;
229        }
230    
231        public ComplexFloat divi(ComplexFloat c) {
232            return divi(c, this);
233        }
234        
235        public ComplexFloat divi(float v, ComplexFloat result) {
236            if (this == result) {
237                r /= v;
238                i /= v;
239            } else {
240                result.r = r / v;
241                result.i = i / v;
242            }
243            return this;
244        }
245        
246        public ComplexFloat divi(float v) {
247            return divi(v, this);
248        }
249    
250        public ComplexFloat div(float v) {
251            return dup().divi(v);
252        }
253    
254        /** Return the absolute value */
255        public float abs() {
256            return (float) Math.sqrt(r * r + i * i);
257        }
258    
259        /** Returns the argument of a complex number. */
260        public float arg() {
261            return (float) Math.acos(r/abs());
262        }
263    
264        public ComplexFloat invi() {
265            float d = r * r + i * i;
266            r = r / d;
267            i = -i / d;
268            return this;
269        }
270        
271        public ComplexFloat inv() {
272            return dup().invi();
273        }
274    
275        public ComplexFloat neg() {
276            return dup().negi();
277        }
278    
279        public ComplexFloat negi() {
280            r = -r;
281            i = -i;
282            return this;
283        }
284    
285        public ComplexFloat conji() {
286            i = -i;
287            return this;
288        }
289        
290        public ComplexFloat conj() {
291            return dup().conji();
292        }
293    
294        public ComplexFloat sqrt() {
295            float a = abs();
296            float s2 = (float)Math.sqrt(2);
297            float p = (float)Math.sqrt(a + r)/s2;
298            float q = (float)Math.sqrt(a - r)/s2 * Math.signum(i);
299            return new ComplexFloat(p, q);
300        }
301        
302        /**
303         * Comparing two DoubleComplex values.
304         */
305        public boolean equals(Object o) {
306            if (!(o instanceof ComplexFloat)) {
307                return false;
308            }
309            ComplexFloat c = (ComplexFloat) o;
310    
311            return eq(c);
312        }
313    
314        public boolean eq(ComplexFloat c) {
315            return Math.abs(r - c.r) + Math.abs(i - c.i) < (float) 1e-6;
316        }
317    
318        public boolean ne(ComplexFloat c) {
319            return !eq(c);
320        }
321    
322        public boolean isZero() {
323            return r == 0.0f && i == 0.0f;
324        }
325        
326        public boolean isReal() {
327            return i == 0.0f;
328        }
329        
330        public boolean isImag() {
331            return r == 0.0f;
332        }
333    }