View Javadoc

1   /*
2    * Copyright 2003-2005 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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                 // ignore exception
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 }