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.DoubleBuffer;
040    
041    /**
042     * A complex value with double precision.
043     * 
044     * @author Mikio L. Braun
045     * 
046     */
047    public class ComplexDouble {
048    
049        private double r,  i;
050        public static final ComplexDouble UNIT = new ComplexDouble(1.0, 0.0);
051        public static final ComplexDouble I = new ComplexDouble(0.0, 1.0);
052        public static final ComplexDouble NEG_UNIT = new ComplexDouble(-1.0, 0.0);
053        public static final ComplexDouble NEG_I = new ComplexDouble(0.0, -1.0);
054        public static final ComplexDouble ZERO = new ComplexDouble(0.0);
055    
056        public ComplexDouble(double real, double imag) {
057            r = real;
058            i = imag;
059        }
060    
061        public ComplexDouble(double real) {
062            this(real, 0.0);
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 ComplexDouble set(double real, double imag) {
074            r = real;
075            i = imag;
076            return this;
077        }
078    
079        public double real() {
080            return r;
081        }
082    
083        public double imag() {
084            return i;
085        }
086    
087        public ComplexDouble dup() {
088            return new ComplexDouble(r, i);
089        }
090    
091        public ComplexDouble copy(ComplexDouble other) {
092            r = other.r;
093            i = other.i;
094            return this;
095        }
096    
097        /** Add two complex numbers in-place */
098        public ComplexDouble addi(ComplexDouble c, ComplexDouble 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 ComplexDouble addi(ComplexDouble c) {
111            return addi(c, this);
112        }
113    
114        /** Add two complex numbers. */
115        public ComplexDouble add(ComplexDouble c) {
116            return dup().addi(c);
117        }
118    
119        /** Add a real number to a complex number in-place. */
120        public ComplexDouble addi(double a, ComplexDouble 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 ComplexDouble addi(double c) {
132            return addi(c, this);
133        }
134    
135        /** Add a real number to a complex number. */
136        public ComplexDouble add(double c) {
137            return dup().addi(c);
138        }
139    
140        /** Subtract two complex numbers, in-place */
141        public ComplexDouble subi(ComplexDouble c, ComplexDouble 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 ComplexDouble subi(ComplexDouble c) {
153            return subi(c, this);
154        }
155    
156        /** Subtract two complex numbers */
157        public ComplexDouble sub(ComplexDouble c) {
158            return dup().subi(c);
159        }
160    
161        public ComplexDouble subi(double a, ComplexDouble 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 ComplexDouble subi(double a) {
172            return subi(a, this);
173        }
174    
175        public ComplexDouble sub(double r) {
176            return dup().subi(r);
177        }
178    
179        /** Multiply two complex numbers, inplace */
180        public ComplexDouble muli(ComplexDouble c, ComplexDouble result) {
181            double newR = r * c.r - i * c.i;
182            double newI = r * c.i + i * c.r;
183            result.r = newR;
184            result.i = newI;
185            return result;
186        }
187        
188        public ComplexDouble muli(ComplexDouble c) {
189            return muli(c, this);
190        }
191    
192        /** Multiply two complex numbers */
193        public ComplexDouble mul(ComplexDouble c) {
194            return dup().muli(c);
195        }
196    
197        public ComplexDouble mul(double v) {
198            return dup().muli(v);
199        }
200    
201        public ComplexDouble muli(double v, ComplexDouble 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 ComplexDouble muli(double v) {
213            return muli(v, this);
214        }
215    
216        /** Divide two complex numbers */
217        public ComplexDouble div(ComplexDouble c) {
218            return dup().divi(c);
219        }
220    
221        /** Divide two complex numbers, in-place */
222        public ComplexDouble divi(ComplexDouble c, ComplexDouble result) {
223            double d = c.r * c.r + c.i * c.i;
224            double newR = (r * c.r + i * c.i) / d;
225            double newI = (i * c.r - r * c.i) / d;
226            result.r = newR;
227            result.i = newI;
228            return result;
229        }
230    
231        public ComplexDouble divi(ComplexDouble c) {
232            return divi(c, this);
233        }
234        
235        public ComplexDouble divi(double v, ComplexDouble 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 ComplexDouble divi(double v) {
247            return divi(v, this);
248        }
249    
250        public ComplexDouble div(double v) {
251            return dup().divi(v);
252        }
253    
254        /** Return the absolute value */
255        public double abs() {
256            return (double) Math.sqrt(r * r + i * i);
257        }
258    
259        /** Returns the argument of a complex number. */
260        public double arg() {
261            return (double) Math.acos(r/abs());
262        }
263    
264        public ComplexDouble invi() {
265            double d = r * r + i * i;
266            r = r / d;
267            i = -i / d;
268            return this;
269        }
270        
271        public ComplexDouble inv() {
272            return dup().invi();
273        }
274    
275        public ComplexDouble neg() {
276            return dup().negi();
277        }
278    
279        public ComplexDouble negi() {
280            r = -r;
281            i = -i;
282            return this;
283        }
284    
285        public ComplexDouble conji() {
286            i = -i;
287            return this;
288        }
289        
290        public ComplexDouble conj() {
291            return dup().conji();
292        }
293    
294        public ComplexDouble sqrt() {
295            double a = abs();
296            double s2 = (double)Math.sqrt(2);
297            double p = (double)Math.sqrt(a + r)/s2;
298            double q = (double)Math.sqrt(a - r)/s2 * Math.signum(i);
299            return new ComplexDouble(p, q);
300        }
301        
302        /**
303         * Comparing two DoubleComplex values.
304         */
305        public boolean equals(Object o) {
306            if (!(o instanceof ComplexDouble)) {
307                return false;
308            }
309            ComplexDouble c = (ComplexDouble) o;
310    
311            return eq(c);
312        }
313    
314        public boolean eq(ComplexDouble c) {
315            return Math.abs(r - c.r) + Math.abs(i - c.i) < (double) 1e-6;
316        }
317    
318        public boolean ne(ComplexDouble c) {
319            return !eq(c);
320        }
321    
322        public boolean isZero() {
323            return r == 0.0 && i == 0.0;
324        }
325        
326        public boolean isReal() {
327            return i == 0.0;
328        }
329        
330        public boolean isImag() {
331            return r == 0.0;
332        }
333    }