001: /*
002: * Copyright 2003-2005 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.commons.math.complex;
018:
019: import java.io.Serializable;
020: import org.apache.commons.math.util.MathUtils;
021:
022: /**
023: * Representation of a Complex number - a number which has both a
024: * real and imaginary part.
025: * <p>
026: * Implementations of arithmetic operations handle <code>NaN</code> and
027: * infinite values according to the rules for {@link java.lang.Double}
028: * arithmetic, applying definitional formulas and returning <code>NaN</code> or
029: * infinite values in real or imaginary parts as these arise in computation.
030: * See individual method javadocs for details.
031: * <p>
032: * {@link #equals} identifies all values with <code>NaN</code> in either real
033: * or imaginary part - e.g., <pre>
034: * <code>1 + NaNi == NaN + i == NaN + NaNi.</code></pre>
035: *
036: * @author Apache Software Foundation
037: * @version $Revision: 349309 $ $Date: 2005-11-27 13:55:08 -0700 (Sun, 27 Nov 2005) $
038: */
039: public class Complex implements Serializable {
040:
041: /** Serializable version identifier */
042: private static final long serialVersionUID = -6530173849413811929L;
043:
044: /** The square root of -1. A number representing "0.0 + 1.0i" */
045: public static final Complex I = new Complex(0.0, 1.0);
046:
047: /** A complex number representing "NaN + NaNi" */
048: public static final Complex NaN = new Complex(Double.NaN,
049: Double.NaN);
050:
051: /** A complex number representing "1.0 + 0.0i" */
052: public static final Complex ONE = new Complex(1.0, 0.0);
053:
054: /** A complex number representing "0.0 + 0.0i" */
055: public static final Complex ZERO = new Complex(0.0, 0.0);
056:
057: /** The imaginary part */
058: protected double imaginary;
059:
060: /** The real part */
061: protected double real;
062:
063: /**
064: * Create a complex number given the real and imaginary parts.
065: *
066: * @param real the real part
067: * @param imaginary the imaginary part
068: */
069: public Complex(double real, double imaginary) {
070: super ();
071: this .real = real;
072: this .imaginary = imaginary;
073: }
074:
075: /**
076: * Return the absolute value of this complex number.
077: * <p>
078: * Returns <code>NaN</code> if either real or imaginary part is
079: * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
080: * neither part is <code>NaN</code>, but at least one part takes an infinite
081: * value.
082: *
083: * @return the absolute value
084: */
085: public double abs() {
086: if (isNaN()) {
087: return Double.NaN;
088: }
089:
090: if (isInfinite()) {
091: return Double.POSITIVE_INFINITY;
092: }
093:
094: if (Math.abs(real) < Math.abs(imaginary)) {
095: if (imaginary == 0.0) {
096: return Math.abs(real);
097: }
098: double q = real / imaginary;
099: return (Math.abs(imaginary) * Math.sqrt(1 + q * q));
100: } else {
101: if (real == 0.0) {
102: return Math.abs(imaginary);
103: }
104: double q = imaginary / real;
105: return (Math.abs(real) * Math.sqrt(1 + q * q));
106: }
107: }
108:
109: /**
110: * Return the sum of this complex number and the given complex number.
111: * <p>
112: * Uses the definitional formula
113: * <pre>
114: * (a + bi) + (c + di) = (a+c) + (b+d)i
115: * </pre>
116: * <p>
117: * If either this or <code>rhs</code> has a NaN value in either part,
118: * {@link #NaN} is returned; otherwise Inifinite and NaN values are
119: * returned in the parts of the result according to the rules for
120: * {@link java.lang.Double} arithmetic.
121: *
122: * @param rhs the other complex number
123: * @return the complex number sum
124: * @throws NullPointerException if <code>rhs</code> is null
125: */
126: public Complex add(Complex rhs) {
127: return new Complex(real + rhs.getReal(), imaginary
128: + rhs.getImaginary());
129: }
130:
131: /**
132: * Return the conjugate of this complex number. The conjugate of
133: * "A + Bi" is "A - Bi".
134: * <p>
135: * {@link #NaN} is returned if either the real or imaginary
136: * part of this Complex number equals <code>Double.NaN</code>.
137: * <p>
138: * If the imaginary part is infinite, and the real part is not NaN,
139: * the returned value has infinite imaginary part of the opposite
140: * sign - e.g. the conjugate of <code>1 + POSITIVE_INFINITY i</code>
141: * is <code>1 - NEGATIVE_INFINITY i</code>
142: *
143: * @return the conjugate of this Complex object
144: */
145: public Complex conjugate() {
146: if (isNaN()) {
147: return NaN;
148: }
149: return new Complex(real, -imaginary);
150: }
151:
152: /**
153: * Return the quotient of this complex number and the given complex number.
154: * <p>
155: * Implements the definitional formula
156: * <pre><code>
157: * a + bi ac + bd + (bc - ad)i
158: * ----------- = -------------------------
159: * c + di c<sup>2</sup> + d<sup>2</sup>
160: * </code></pre>
161: * but uses
162: * <a href="http://doi.acm.org/10.1145/1039813.1039814">
163: * prescaling of operands</a> to limit the effects of overflows and
164: * underflows in the computation.
165: * <p>
166: * Infinite and NaN values are handled / returned according to the
167: * following rules, applied in the order presented:
168: * <ul>
169: * <li>If either this or <code>rhs</code> has a NaN value in either part,
170: * {@link #NaN} is returned.</li>
171: * <li>If <code>rhs</code> equals {@link #ZERO}, {@link #NaN} is returned.
172: * </li>
173: * <li>If this and <code>rhs</code> are both infinite,
174: * {@link #NaN} is returned.</li>
175: * <li>If this is finite (i.e., has no infinite or NaN parts) and
176: * <code>rhs</code> is infinite (one or both parts infinite),
177: * {@link #ZERO} is returned.</li>
178: * <li>If this is infinite and <code>rhs</code> is finite, NaN values are
179: * returned in the parts of the result if the {@link java.lang.Double}
180: * rules applied to the definitional formula force NaN results.</li>
181: * </ul>
182: *
183: * @param rhs the other complex number
184: * @return the complex number quotient
185: * @throws NullPointerException if <code>rhs</code> is null
186: */
187: public Complex divide(Complex rhs) {
188: if (isNaN() || rhs.isNaN()) {
189: return NaN;
190: }
191:
192: double c = rhs.getReal();
193: double d = rhs.getImaginary();
194: if (c == 0.0 && d == 0.0) {
195: return NaN;
196: }
197:
198: if (rhs.isInfinite() && !isInfinite()) {
199: return ZERO;
200: }
201:
202: if (Math.abs(c) < Math.abs(d)) {
203: if (d == 0.0) {
204: return new Complex(real / c, imaginary / c);
205: }
206: double q = c / d;
207: double denominator = c * q + d;
208: return new Complex((real * q + imaginary) / denominator,
209: (imaginary * q - real) / denominator);
210: } else {
211: if (c == 0.0) {
212: return new Complex(imaginary / d, -real / c);
213: }
214: double q = d / c;
215: double denominator = d * q + c;
216: return new Complex((imaginary * q + real) / denominator,
217: (imaginary - real * q) / denominator);
218: }
219: }
220:
221: /**
222: * Test for the equality of two Complex objects.
223: * <p>
224: * If both the real and imaginary parts of two Complex numbers
225: * are exactly the same, and neither is <code>Double.NaN</code>, the two
226: * Complex objects are considered to be equal.
227: * <p>
228: * All <code>NaN</code> values are considered to be equal - i.e, if either
229: * (or both) real and imaginary parts of the complex number are equal
230: * to <code>Double.NaN</code>, the complex number is equal to
231: * <code>Complex.NaN</code>.
232: *
233: * @param other Object to test for equality to this
234: * @return true if two Complex objects are equal, false if
235: * object is null, not an instance of Complex, or
236: * not equal to this Complex instance
237: *
238: */
239: public boolean equals(Object other) {
240: boolean ret;
241:
242: if (this == other) {
243: ret = true;
244: } else if (other == null) {
245: ret = false;
246: } else {
247: try {
248: Complex rhs = (Complex) other;
249: if (rhs.isNaN()) {
250: ret = this .isNaN();
251: } else {
252: ret = (Double.doubleToRawLongBits(real) == Double
253: .doubleToRawLongBits(rhs.getReal()))
254: && (Double.doubleToRawLongBits(imaginary) == Double
255: .doubleToRawLongBits(rhs
256: .getImaginary()));
257: }
258: } catch (ClassCastException ex) {
259: // ignore exception
260: ret = false;
261: }
262: }
263:
264: return ret;
265: }
266:
267: /**
268: * Get a hashCode for the complex number.
269: * <p>
270: * All NaN values have the same hash code.
271: *
272: * @return a hash code value for this object
273: */
274: public int hashCode() {
275: if (isNaN()) {
276: return 7;
277: }
278: return 37 * (17 * MathUtils.hash(imaginary) + MathUtils
279: .hash(real));
280: }
281:
282: /**
283: * Access the imaginary part.
284: *
285: * @return the imaginary part
286: */
287: public double getImaginary() {
288: return imaginary;
289: }
290:
291: /**
292: * Access the real part.
293: *
294: * @return the real part
295: */
296: public double getReal() {
297: return real;
298: }
299:
300: /**
301: * Returns true if either or both parts of this complex number is NaN;
302: * false otherwise
303: *
304: * @return true if either or both parts of this complex number is NaN;
305: * false otherwise
306: */
307: public boolean isNaN() {
308: return Double.isNaN(real) || Double.isNaN(imaginary);
309: }
310:
311: /**
312: * Returns true if either the real or imaginary part of this complex number
313: * takes an infinite value (either <code>Double.POSITIVE_INFINITY</code> or
314: * <code>Double.NEGATIVE_INFINITY</code>) and neither part
315: * is <code>NaN</code>.
316: *
317: * @return true if one or both parts of this complex number are infinite
318: * and neither part is <code>NaN</code>
319: */
320: public boolean isInfinite() {
321: return !isNaN()
322: && (Double.isInfinite(real) || Double
323: .isInfinite(imaginary));
324: }
325:
326: /**
327: * Return the product of this complex number and the given complex number.
328: * <p>
329: * Implements the definitional formula:
330: * <pre><code>
331: * (a + bi)(c + di) = (ac - bd) + (ad + bc)i
332: * </code></pre>
333: * <p>
334: * Returns {@link #NaN} if either this or <code>rhs</code> has one or more
335: * NaN parts.
336: * <p>
337: * Returns NaN or infinite values in components of the result per the
338: * definitional formula and and the rules for {@link java.lang.Double}
339: * arithmetic. Examples:
340: * <pre><code>
341: * (1 + i) (INF + i) = INF + INFi
342: * (1 + INFi) (1 - INFi) = INF + NaNi
343: * (-INF + -INFi)(1 + NaNi) = NaN + NaNi
344: * </code></pre>
345: *
346: * @param rhs the other complex number
347: * @return the complex number product
348: * @throws NullPointerException if <code>rhs</code> is null
349: */
350: public Complex multiply(Complex rhs) {
351: if (isNaN() || rhs.isNaN()) {
352: return NaN;
353: }
354: return new Complex(real * rhs.real - imaginary * rhs.imaginary,
355: real * rhs.imaginary + imaginary * rhs.real);
356: }
357:
358: /**
359: * Return the additive inverse of this complex number.
360: * <p>
361: * Returns <code>Complex.NaN</code> if either real or imaginary
362: * part of this Complex number equals <code>Double.NaN</code>.
363: *
364: * @return the negation of this complex number
365: */
366: public Complex negate() {
367: if (isNaN()) {
368: return NaN;
369: }
370:
371: return new Complex(-real, -imaginary);
372: }
373:
374: /**
375: * Return the difference between this complex number and the given complex
376: * number.
377: * <p>
378: * Uses the definitional formula
379: * <pre>
380: * (a + bi) - (c + di) = (a-c) + (b-d)i
381: * </pre>
382: * <p>
383: * If either this or <code>rhs</code> has a NaN value in either part,
384: * {@link #NaN} is returned; otherwise inifinite and NaN values are
385: * returned in the parts of the result according to the rules for
386: * {@link java.lang.Double} arithmetic.
387: *
388: * @param rhs the other complex number
389: * @return the complex number difference
390: * @throws NullPointerException if <code>rhs</code> is null
391: */
392: public Complex subtract(Complex rhs) {
393: if (isNaN() || rhs.isNaN()) {
394: return NaN;
395: }
396:
397: return new Complex(real - rhs.getReal(), imaginary
398: - rhs.getImaginary());
399: }
400: }
|