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
039/**
040 * A complex value with float precision.
041 *
042 * @author Mikio L. Braun
043 */
044public class ComplexFloat {
045
046  private float r, i;
047  public static final ComplexFloat UNIT = new ComplexFloat(1.0f, 0.0f);
048  public static final ComplexFloat I = new ComplexFloat(0.0f, 1.0f);
049  public static final ComplexFloat NEG_UNIT = new ComplexFloat(-1.0f, 0.0f);
050  public static final ComplexFloat NEG_I = new ComplexFloat(0.0f, -1.0f);
051  public static final ComplexFloat ZERO = new ComplexFloat(0.0f);
052
053  public ComplexFloat(float real, float imag) {
054    r = real;
055    i = imag;
056  }
057
058  public ComplexFloat(float real) {
059    this(real, 0.0f);
060  }
061
062  public String toString() {
063    if (i >= 0) {
064      return r + " + " + i + "i";
065    } else {
066      return r + " - " + (-i) + "i";
067    }
068  }
069
070  public ComplexFloat set(float real, float imag) {
071    r = real;
072    i = imag;
073    return this;
074  }
075
076  public float real() {
077    return r;
078  }
079
080  public float imag() {
081    return i;
082  }
083
084  public ComplexFloat dup() {
085    return new ComplexFloat(r, i);
086  }
087
088  public ComplexFloat copy(ComplexFloat other) {
089    r = other.r;
090    i = other.i;
091    return this;
092  }
093
094  /**
095   * Add two complex numbers in-place
096   *
097   * @param c      other complex number
098   * @param result complex number where result is stored
099   * @return same as result
100   */
101  public ComplexFloat addi(ComplexFloat c, ComplexFloat result) {
102    if (this == result) {
103      r += c.r;
104      i += c.i;
105    } else {
106      result.r = r + c.r;
107      result.i = i + c.i;
108    }
109    return result;
110  }
111
112  /**
113   * Add two complex numbers in-place storing the result in this.
114   *
115   * @param c other complex number
116   * @return resulting complex number
117   */
118  public ComplexFloat addi(ComplexFloat c) {
119    return addi(c, this);
120  }
121
122  /**
123   * Add two complex numbers.
124   *
125   * @param c other complex number
126   * @return new complex number with result
127   */
128  public ComplexFloat add(ComplexFloat c) {
129    return dup().addi(c);
130  }
131
132  /**
133   * Add a real number to a complex number in-place.
134   *
135   * @param a      real number to add
136   * @param result complex number to hold result
137   * @return same as result
138   */
139  public ComplexFloat addi(float a, ComplexFloat result) {
140    if (this == result) {
141      r += a;
142    } else {
143      result.r = r + a;
144      result.i = i;
145    }
146    return result;
147  }
148
149  /**
150   * Add a real number to complex number in-place, storing the result in this.
151   *
152   * @param c real number to add
153   * @return resulting complex number
154   */
155  public ComplexFloat addi(float c) {
156    return addi(c, this);
157  }
158
159  /**
160   * Add a real number to a complex number.
161   *
162   * @param c real number to add
163   * @return new complex number with result
164   */
165  public ComplexFloat add(float c) {
166    return dup().addi(c);
167  }
168
169  /**
170   * Subtract two complex numbers, in-place
171   *
172   * @param c      complex number to subtract
173   * @param result resulting complex number
174   * @return same as result
175   */
176  public ComplexFloat subi(ComplexFloat c, ComplexFloat result) {
177    if (this == result) {
178      r -= c.r;
179      i -= c.i;
180    } else {
181      result.r = r - c.r;
182      result.i = i - c.i;
183    }
184    return this;
185  }
186
187  public ComplexFloat subi(ComplexFloat c) {
188    return subi(c, this);
189  }
190
191  /**
192   * Subtract two complex numbers
193   *
194   * @param c complex number to subtract
195   * @return new complex number with result
196   */
197  public ComplexFloat sub(ComplexFloat c) {
198    return dup().subi(c);
199  }
200
201  public ComplexFloat subi(float a, ComplexFloat result) {
202    if (this == result) {
203      r -= a;
204    } else {
205      result.r = r - a;
206      result.i = i;
207    }
208    return result;
209  }
210
211  public ComplexFloat subi(float a) {
212    return subi(a, this);
213  }
214
215  public ComplexFloat sub(float r) {
216    return dup().subi(r);
217  }
218
219  /**
220   * Multiply two complex numbers, in-place
221   *
222   * @param c      other complex number
223   * @param result complex number where product is stored
224   * @return same as result
225   */
226  public ComplexFloat muli(ComplexFloat c, ComplexFloat result) {
227    float newR = r * c.r - i * c.i;
228    float newI = r * c.i + i * c.r;
229    result.r = newR;
230    result.i = newI;
231    return result;
232  }
233
234  public ComplexFloat muli(ComplexFloat c) {
235    return muli(c, this);
236  }
237
238  /**
239   * Multiply two complex numbers
240   *
241   * @param c other complex number
242   * @return new complex number with product of this and c
243   */
244  public ComplexFloat mul(ComplexFloat c) {
245    return dup().muli(c);
246  }
247
248  public ComplexFloat mul(float v) {
249    return dup().muli(v);
250  }
251
252  public ComplexFloat muli(float v, ComplexFloat result) {
253    if (this == result) {
254      r *= v;
255      i *= v;
256    } else {
257      result.r = r * v;
258      result.i = i * v;
259    }
260    return this;
261  }
262
263  public ComplexFloat muli(float v) {
264    return muli(v, this);
265  }
266
267  /**
268   * Divide two complex numbers
269   *
270   * @param c complex number to divide this by
271   * @return new complex number with quotient of this and c
272   */
273  public ComplexFloat div(ComplexFloat c) {
274    return dup().divi(c);
275  }
276
277  /**
278   * Divide two complex numbers, in-place
279   *
280   * @param c      complex number to divide this by
281   * @param result complex number to hold result
282   * @return same as result
283   */
284  public ComplexFloat divi(ComplexFloat c, ComplexFloat result) {
285    float d = c.r * c.r + c.i * c.i;
286    float newR = (r * c.r + i * c.i) / d;
287    float newI = (i * c.r - r * c.i) / d;
288    result.r = newR;
289    result.i = newI;
290    return result;
291  }
292
293  public ComplexFloat divi(ComplexFloat c) {
294    return divi(c, this);
295  }
296
297  public ComplexFloat divi(float v, ComplexFloat result) {
298    if (this == result) {
299      r /= v;
300      i /= v;
301    } else {
302      result.r = r / v;
303      result.i = i / v;
304    }
305    return this;
306  }
307
308  public ComplexFloat divi(float v) {
309    return divi(v, this);
310  }
311
312  public ComplexFloat div(float v) {
313    return dup().divi(v);
314  }
315
316  /**
317   * Return the absolute value
318   *
319   * @return the result (length of the vector in 2d plane)
320   */
321  public float abs() {
322    return (float) Math.sqrt(r * r + i * i);
323  }
324
325  /**
326   * Returns the argument of a complex number.
327   *
328   * @return the result (angle in radians of the vector in 2d plane)
329   */
330  public float arg() {
331    return (float) Math.atan2(i, r);
332  }
333
334  public ComplexFloat invi() {
335    float d = r * r + i * i;
336    r = r / d;
337    i = -i / d;
338    return this;
339  }
340
341  public ComplexFloat inv() {
342    return dup().invi();
343  }
344
345  public ComplexFloat neg() {
346    return dup().negi();
347  }
348
349  public ComplexFloat negi() {
350    r = -r;
351    i = -i;
352    return this;
353  }
354
355  public ComplexFloat conji() {
356    i = -i;
357    return this;
358  }
359
360  public ComplexFloat conj() {
361    return dup().conji();
362  }
363
364  public ComplexFloat sqrt() {
365    float a = abs();
366    float s2 = (float) Math.sqrt(2);
367    float p = (float) Math.sqrt(a + r) / s2;
368    float sgn = Math.signum(i);
369    if (sgn == 0.0f) {
370      sgn = 1.0f;
371    }
372    float q = (float) Math.sqrt(a - r) / s2 * Math.signum(sgn);
373    return new ComplexFloat(p, q);
374  }
375
376  /**
377   * Comparing two ComplexFloat values.
378   *
379   * @param o object to compare this against
380   * @return true if both numbers have the same value
381   */
382  public boolean equals(Object o) {
383    if (!(o instanceof ComplexFloat)) {
384      return false;
385    }
386    ComplexFloat c = (ComplexFloat) o;
387
388    return r == c.r && i == c.i;
389  }
390
391  public int hashCode() {
392    return Float.valueOf(r).hashCode() ^ Float.valueOf(i).hashCode();
393  }
394
395  public boolean eq(ComplexFloat c) {
396    return Math.abs(r - c.r) + Math.abs(i - c.i) < (float) 1e-6;
397  }
398
399  public boolean ne(ComplexFloat c) {
400    return !eq(c);
401  }
402
403  public boolean isZero() {
404    return r == 0.0f && i == 0.0f;
405  }
406
407  public boolean isReal() {
408    return i == 0.0f;
409  }
410
411  public boolean isImag() {
412    return r == 0.0f;
413  }
414}