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
037package org.jblas;
038
039import java.nio.DoubleBuffer;
040
041/**
042 * A complex value with double precision.
043 * 
044 * @author Mikio L. Braun
045 * 
046 */
047public 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}