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.core;
038    
039    import static java.lang.Math.sqrt;
040    
041    import java.nio.FloatBuffer;
042    
043    /**
044     * A complex value with float precision.
045     * 
046     * @author Mikio L. Braun
047     * 
048     */
049    public class ComplexFloat {
050    
051        private float r,  i;
052        public static final ComplexFloat UNIT = new ComplexFloat(1.0f, 0.0f);
053        public static final ComplexFloat I = new ComplexFloat(0.0f, 1.0f);
054        public static final ComplexFloat NEG_UNIT = new ComplexFloat(-1.0f, 0.0f);
055        public static final ComplexFloat NEG_I = new ComplexFloat(0.0f, -1.0f);
056        public static final ComplexFloat ZERO = new ComplexFloat(0.0f);
057    
058        public ComplexFloat(float real, float imag) {
059            r = real;
060            i = imag;
061        }
062    
063        public ComplexFloat(float real) {
064            this(real, 0.0f);
065        }
066    
067        public String toString() {
068            if (i >= 0) {
069                return r + " + " + i + "i";
070            } else {
071                return r + " - " + (-i) + "i";
072            }
073        }
074    
075        public ComplexFloat set(float real, float imag) {
076            r = real;
077            i = imag;
078            return this;
079        }
080    
081        public float real() {
082            return r;
083        }
084    
085        public float imag() {
086            return i;
087        }
088    
089        public ComplexFloat dup() {
090            return new ComplexFloat(r, i);
091        }
092    
093        public ComplexFloat copy(ComplexFloat other) {
094            r = other.r;
095            i = other.i;
096            return this;
097        }
098    
099        /** Add two complex numbers in-place */
100        public ComplexFloat addi(ComplexFloat c, ComplexFloat result) {
101            if (this == result) {
102                r += c.r;
103                i += c.i;
104            } else {
105                result.r = r + c.r;
106                result.i = i + c.i;
107            }
108            return result;
109        }
110    
111        /** Add two complex numbers in-place storing the result in this. */
112        public ComplexFloat addi(ComplexFloat c) {
113            return addi(c, this);
114        }
115    
116        /** Add two complex numbers. */
117        public ComplexFloat add(ComplexFloat c) {
118            return dup().addi(c);
119        }
120    
121        /** Add a real number to a complex number in-place. */
122        public ComplexFloat addi(float a, ComplexFloat result) {
123            if (this == result) {
124                r += a;
125            } else {
126                result.r = r + a;
127                result.i = i;
128            }
129            return result;
130        }
131    
132        /** Add a real number to complex number in-place, storing the result in this. */
133        public ComplexFloat addi(float c) {
134            return addi(c, this);
135        }
136    
137        /** Add a real number to a complex number. */
138        public ComplexFloat add(float c) {
139            return dup().addi(c);
140        }
141    
142        /** Subtract two complex numbers, in-place */
143        public ComplexFloat subi(ComplexFloat c, ComplexFloat result) {
144            if (this == result) {
145                r -= c.r;
146                i -= c.i;
147            } else {
148                result.r = r - c.r;
149                result.i = i - c.i;
150            }
151            return this;
152        }
153        
154        public ComplexFloat subi(ComplexFloat c) {
155            return subi(c, this);
156        }
157    
158        /** Subtract two complex numbers */
159        public ComplexFloat sub(ComplexFloat c) {
160            return dup().subi(c);
161        }
162    
163        public ComplexFloat subi(float a, ComplexFloat result) {
164            if (this == result) {
165                r -= a;
166            } else {
167                result.r = r - a;
168                result.i = i;
169            }
170            return result;
171        }
172        
173        public ComplexFloat subi(float a) {
174            return subi(a, this);
175        }
176    
177        public ComplexFloat sub(float r) {
178            return dup().subi(r);
179        }
180    
181        /** Multiply two complex numbers, inplace */
182        public ComplexFloat muli(ComplexFloat c, ComplexFloat result) {
183            float newR = r * c.r - i * c.i;
184            float newI = r * c.i + i * c.r;
185            result.r = newR;
186            result.i = newI;
187            return result;
188        }
189        
190        public ComplexFloat muli(ComplexFloat c) {
191            return muli(c, this);
192        }
193    
194        /** Multiply two complex numbers */
195        public ComplexFloat mul(ComplexFloat c) {
196            return dup().muli(c);
197        }
198    
199        public ComplexFloat mul(float v) {
200            return dup().muli(v);
201        }
202    
203        public ComplexFloat muli(float v, ComplexFloat result) {
204            if (this == result) {
205                r *= v;
206                i *= v;    
207            } else {
208                result.r = r * v;
209                result.i = i * v;
210            }
211            return this;
212        }
213        
214        public ComplexFloat muli(float v) {
215            return muli(v, this);
216        }
217    
218        /** Divide two complex numbers */
219        public ComplexFloat div(ComplexFloat c) {
220            return dup().divi(c);
221        }
222    
223        /** Divide two complex numbers, in-place */
224        public ComplexFloat divi(ComplexFloat c, ComplexFloat result) {
225            float d = c.r * c.r + c.i * c.i;
226            float newR = (r * c.r + i * c.i) / d;
227            float newI = (i * c.r - r * c.i) / d;
228            result.r = newR;
229            result.i = newI;
230            return result;
231        }
232    
233        public ComplexFloat divi(ComplexFloat c) {
234            return divi(c, this);
235        }
236        
237        public ComplexFloat divi(float v, ComplexFloat result) {
238            if (this == result) {
239                r /= v;
240                i /= v;
241            } else {
242                result.r = r / v;
243                result.i = i / v;
244            }
245            return this;
246        }
247        
248        public ComplexFloat divi(float v) {
249            return divi(v, this);
250        }
251    
252        public ComplexFloat div(float v) {
253            return dup().divi(v);
254        }
255    
256        /** Return the absolute value */
257        public float abs() {
258            return (float) sqrt(r * r + i * i);
259        }
260    
261        public ComplexFloat invi() {
262            float d = r * r + i * i;
263            r = r / d;
264            i = -i / d;
265            return this;
266        }
267        
268        public ComplexFloat inv() {
269            return dup().invi();
270        }
271    
272        public ComplexFloat neg() {
273            return dup().negi();
274        }
275    
276        public ComplexFloat negi() {
277            r = -r;
278            i = -i;
279            return this;
280        }
281    
282        public ComplexFloat conji() {
283            i = -i;
284            return this;
285        }
286        
287        public ComplexFloat conj() {
288            return dup().conji();
289        }
290        
291        /**
292         * Comparing two DoubleComplex values.
293         */
294        public boolean equals(Object o) {
295            if (!(o instanceof ComplexFloat)) {
296                return false;
297            }
298            ComplexFloat c = (ComplexFloat) o;
299    
300            return eq(c);
301        }
302    
303        public boolean eq(ComplexFloat c) {
304            return Math.abs(r - c.r) + Math.abs(i - c.i) < (float) 1e-6;
305        }
306    
307        public boolean ne(ComplexFloat c) {
308            return !eq(c);
309        }
310    
311        public boolean isZero() {
312            return r == 0.0f && i == 0.0f;
313        }
314        
315        public boolean isReal() {
316            return i == 0.0f;
317        }
318        
319        public boolean isImag() {
320            return r == 0.0f;
321        }
322    }