1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math.complex;
18
19 import java.io.Serializable;
20 import org.apache.commons.math.util.MathUtils;
21
22 /**
23 * Representation of a Complex number - a number which has both a
24 * real and imaginary part.
25 * <p>
26 * Implementations of arithmetic operations handle <code>NaN</code> and
27 * infinite values according to the rules for {@link java.lang.Double}
28 * arithmetic, applying definitional formulas and returning <code>NaN</code> or
29 * infinite values in real or imaginary parts as these arise in computation.
30 * See individual method javadocs for details.
31 * <p>
32 * {@link #equals} identifies all values with <code>NaN</code> in either real
33 * or imaginary part - e.g., <pre>
34 * <code>1 + NaNi == NaN + i == NaN + NaNi.</code></pre>
35 *
36 * @author Apache Software Foundation
37 * @version $Revision: 349309 $ $Date: 2005-11-27 13:55:08 -0700 (Sun, 27 Nov 2005) $
38 */
39 public class Complex implements Serializable {
40
41 /** Serializable version identifier */
42 private static final long serialVersionUID = -6530173849413811929L;
43
44 /** The square root of -1. A number representing "0.0 + 1.0i" */
45 public static final Complex I = new Complex(0.0, 1.0);
46
47 /** A complex number representing "NaN + NaNi" */
48 public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
49
50 /** A complex number representing "1.0 + 0.0i" */
51 public static final Complex ONE = new Complex(1.0, 0.0);
52
53 /** A complex number representing "0.0 + 0.0i" */
54 public static final Complex ZERO = new Complex(0.0, 0.0);
55
56 /** The imaginary part */
57 protected double imaginary;
58
59 /** The real part */
60 protected double real;
61
62 /**
63 * Create a complex number given the real and imaginary parts.
64 *
65 * @param real the real part
66 * @param imaginary the imaginary part
67 */
68 public Complex(double real, double imaginary) {
69 super();
70 this.real = real;
71 this.imaginary = imaginary;
72 }
73
74 /**
75 * Return the absolute value of this complex number.
76 * <p>
77 * Returns <code>NaN</code> if either real or imaginary part is
78 * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
79 * neither part is <code>NaN</code>, but at least one part takes an infinite
80 * value.
81 *
82 * @return the absolute value
83 */
84 public double abs() {
85 if (isNaN()) {
86 return Double.NaN;
87 }
88
89 if (isInfinite()) {
90 return Double.POSITIVE_INFINITY;
91 }
92
93 if (Math.abs(real) < Math.abs(imaginary)) {
94 if (imaginary == 0.0) {
95 return Math.abs(real);
96 }
97 double q = real / imaginary;
98 return (Math.abs(imaginary) * Math.sqrt(1 + q*q));
99 } else {
100 if (real == 0.0) {
101 return Math.abs(imaginary);
102 }
103 double q = imaginary / real;
104 return (Math.abs(real) * Math.sqrt(1 + q*q));
105 }
106 }
107
108 /**
109 * Return the sum of this complex number and the given complex number.
110 * <p>
111 * Uses the definitional formula
112 * <pre>
113 * (a + bi) + (c + di) = (a+c) + (b+d)i
114 * </pre>
115 * <p>
116 * If either this or <code>rhs</code> has a NaN value in either part,
117 * {@link #NaN} is returned; otherwise Inifinite and NaN values are
118 * returned in the parts of the result according to the rules for
119 * {@link java.lang.Double} arithmetic.
120 *
121 * @param rhs the other complex number
122 * @return the complex number sum
123 * @throws NullPointerException if <code>rhs</code> is null
124 */
125 public Complex add(Complex rhs) {
126 return new Complex(real + rhs.getReal(),
127 imaginary + rhs.getImaginary());
128 }
129
130 /**
131 * Return the conjugate of this complex number. The conjugate of
132 * "A + Bi" is "A - Bi".
133 * <p>
134 * {@link #NaN} is returned if either the real or imaginary
135 * part of this Complex number equals <code>Double.NaN</code>.
136 * <p>
137 * If the imaginary part is infinite, and the real part is not NaN,
138 * the returned value has infinite imaginary part of the opposite
139 * sign - e.g. the conjugate of <code>1 + POSITIVE_INFINITY i</code>
140 * is <code>1 - NEGATIVE_INFINITY i</code>
141 *
142 * @return the conjugate of this Complex object
143 */
144 public Complex conjugate() {
145 if (isNaN()) {
146 return NaN;
147 }
148 return new Complex(real, -imaginary);
149 }
150
151 /**
152 * Return the quotient of this complex number and the given complex number.
153 * <p>
154 * Implements the definitional formula
155 * <pre><code>
156 * a + bi ac + bd + (bc - ad)i
157 * ----------- = -------------------------
158 * c + di c<sup>2</sup> + d<sup>2</sup>
159 * </code></pre>
160 * but uses
161 * <a href="http://doi.acm.org/10.1145/1039813.1039814">
162 * prescaling of operands</a> to limit the effects of overflows and
163 * underflows in the computation.
164 * <p>
165 * Infinite and NaN values are handled / returned according to the
166 * following rules, applied in the order presented:
167 * <ul>
168 * <li>If either this or <code>rhs</code> has a NaN value in either part,
169 * {@link #NaN} is returned.</li>
170 * <li>If <code>rhs</code> equals {@link #ZERO}, {@link #NaN} is returned.
171 * </li>
172 * <li>If this and <code>rhs</code> are both infinite,
173 * {@link #NaN} is returned.</li>
174 * <li>If this is finite (i.e., has no infinite or NaN parts) and
175 * <code>rhs</code> is infinite (one or both parts infinite),
176 * {@link #ZERO} is returned.</li>
177 * <li>If this is infinite and <code>rhs</code> is finite, NaN values are
178 * returned in the parts of the result if the {@link java.lang.Double}
179 * rules applied to the definitional formula force NaN results.</li>
180 * </ul>
181 *
182 * @param rhs the other complex number
183 * @return the complex number quotient
184 * @throws NullPointerException if <code>rhs</code> is null
185 */
186 public Complex divide(Complex rhs) {
187 if (isNaN() || rhs.isNaN()) {
188 return NaN;
189 }
190
191 double c = rhs.getReal();
192 double d = rhs.getImaginary();
193 if (c == 0.0 && d == 0.0) {
194 return NaN;
195 }
196
197 if (rhs.isInfinite() && !isInfinite()) {
198 return ZERO;
199 }
200
201 if (Math.abs(c) < Math.abs(d)) {
202 if (d == 0.0) {
203 return new Complex(real/c, imaginary/c);
204 }
205 double q = c / d;
206 double denominator = c * q + d;
207 return new Complex((real * q + imaginary) / denominator,
208 (imaginary * q - real) / denominator);
209 } else {
210 if (c == 0.0) {
211 return new Complex(imaginary/d, -real/c);
212 }
213 double q = d / c;
214 double denominator = d * q + c;
215 return new Complex((imaginary * q + real) / denominator,
216 (imaginary - real * q) / denominator);
217 }
218 }
219
220 /**
221 * Test for the equality of two Complex objects.
222 * <p>
223 * If both the real and imaginary parts of two Complex numbers
224 * are exactly the same, and neither is <code>Double.NaN</code>, the two
225 * Complex objects are considered to be equal.
226 * <p>
227 * All <code>NaN</code> values are considered to be equal - i.e, if either
228 * (or both) real and imaginary parts of the complex number are equal
229 * to <code>Double.NaN</code>, the complex number is equal to
230 * <code>Complex.NaN</code>.
231 *
232 * @param other Object to test for equality to this
233 * @return true if two Complex objects are equal, false if
234 * object is null, not an instance of Complex, or
235 * not equal to this Complex instance
236 *
237 */
238 public boolean equals(Object other) {
239 boolean ret;
240
241 if (this == other) {
242 ret = true;
243 } else if (other == null) {
244 ret = false;
245 } else {
246 try {
247 Complex rhs = (Complex)other;
248 if (rhs.isNaN()) {
249 ret = this.isNaN();
250 } else {
251 ret = (Double.doubleToRawLongBits(real) ==
252 Double.doubleToRawLongBits(rhs.getReal())) &&
253 (Double.doubleToRawLongBits(imaginary) ==
254 Double.doubleToRawLongBits(rhs.getImaginary()));
255 }
256 } catch (ClassCastException ex) {
257
258 ret = false;
259 }
260 }
261
262 return ret;
263 }
264
265 /**
266 * Get a hashCode for the complex number.
267 * <p>
268 * All NaN values have the same hash code.
269 *
270 * @return a hash code value for this object
271 */
272 public int hashCode() {
273 if (isNaN()) {
274 return 7;
275 }
276 return 37 * (17 * MathUtils.hash(imaginary) +
277 MathUtils.hash(real));
278 }
279
280 /**
281 * Access the imaginary part.
282 *
283 * @return the imaginary part
284 */
285 public double getImaginary() {
286 return imaginary;
287 }
288
289 /**
290 * Access the real part.
291 *
292 * @return the real part
293 */
294 public double getReal() {
295 return real;
296 }
297
298 /**
299 * Returns true if either or both parts of this complex number is NaN;
300 * false otherwise
301 *
302 * @return true if either or both parts of this complex number is NaN;
303 * false otherwise
304 */
305 public boolean isNaN() {
306 return Double.isNaN(real) || Double.isNaN(imaginary);
307 }
308
309 /**
310 * Returns true if either the real or imaginary part of this complex number
311 * takes an infinite value (either <code>Double.POSITIVE_INFINITY</code> or
312 * <code>Double.NEGATIVE_INFINITY</code>) and neither part
313 * is <code>NaN</code>.
314 *
315 * @return true if one or both parts of this complex number are infinite
316 * and neither part is <code>NaN</code>
317 */
318 public boolean isInfinite() {
319 return !isNaN() &&
320 (Double.isInfinite(real) || Double.isInfinite(imaginary));
321 }
322
323 /**
324 * Return the product of this complex number and the given complex number.
325 * <p>
326 * Implements the definitional formula:
327 * <pre><code>
328 * (a + bi)(c + di) = (ac - bd) + (ad + bc)i
329 * </code></pre>
330 * <p>
331 * Returns {@link #NaN} if either this or <code>rhs</code> has one or more
332 * NaN parts.
333 * <p>
334 * Returns NaN or infinite values in components of the result per the
335 * definitional formula and and the rules for {@link java.lang.Double}
336 * arithmetic. Examples:
337 * <pre><code>
338 * (1 + i) (INF + i) = INF + INFi
339 * (1 + INFi) (1 - INFi) = INF + NaNi
340 * (-INF + -INFi)(1 + NaNi) = NaN + NaNi
341 * </code></pre>
342 *
343 * @param rhs the other complex number
344 * @return the complex number product
345 * @throws NullPointerException if <code>rhs</code> is null
346 */
347 public Complex multiply(Complex rhs) {
348 if (isNaN() || rhs.isNaN()) {
349 return NaN;
350 }
351 return new Complex(real * rhs.real - imaginary * rhs.imaginary,
352 real * rhs.imaginary + imaginary * rhs.real);
353 }
354
355 /**
356 * Return the additive inverse of this complex number.
357 * <p>
358 * Returns <code>Complex.NaN</code> if either real or imaginary
359 * part of this Complex number equals <code>Double.NaN</code>.
360 *
361 * @return the negation of this complex number
362 */
363 public Complex negate() {
364 if (isNaN()) {
365 return NaN;
366 }
367
368 return new Complex(-real, -imaginary);
369 }
370
371 /**
372 * Return the difference between this complex number and the given complex
373 * number.
374 * <p>
375 * Uses the definitional formula
376 * <pre>
377 * (a + bi) - (c + di) = (a-c) + (b-d)i
378 * </pre>
379 * <p>
380 * If either this or <code>rhs</code> has a NaN value in either part,
381 * {@link #NaN} is returned; otherwise inifinite and NaN values are
382 * returned in the parts of the result according to the rules for
383 * {@link java.lang.Double} arithmetic.
384 *
385 * @param rhs the other complex number
386 * @return the complex number difference
387 * @throws NullPointerException if <code>rhs</code> is null
388 */
389 public Complex subtract(Complex rhs) {
390 if (isNaN() || rhs.isNaN()) {
391 return NaN;
392 }
393
394 return new Complex(real - rhs.getReal(),
395 imaginary - rhs.getImaginary());
396 }
397 }