View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math.complex;
19  
20  import java.io.Serializable;
21  import org.apache.commons.math.util.MathUtils;
22  
23  /**
24   * Representation of a Complex number - a number which has both a 
25   * real and imaginary part.
26   * <p>
27   * Implementations of arithmetic operations handle <code>NaN</code> and
28   * infinite values according to the rules for {@link java.lang.Double}
29   * arithmetic, applying definitional formulas and returning <code>NaN</code> or
30   * infinite values in real or imaginary parts as these arise in computation. 
31   * See individual method javadocs for details.</p>
32   * <p>
33   * {@link #equals} identifies all values with <code>NaN</code> in either real 
34   * or imaginary part - e.g., <pre>
35   * <code>1 + NaNi  == NaN + i == NaN + NaNi.</code></pre></p>
36   *
37   * @version $Revision: 620373 $ $Date: 2008-02-10 18:18:39 -0700 (Sun, 10 Feb 2008) $
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 "+INF + INFi" */
51      public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
52  
53      /** A complex number representing "1.0 + 0.0i" */    
54      public static final Complex ONE = new Complex(1.0, 0.0);
55      
56      /** A complex number representing "0.0 + 0.0i" */    
57      public static final Complex ZERO = new Complex(0.0, 0.0);
58      
59      /** 
60       * The imaginary part 
61       * @deprecated to be made final and private in 2.0
62       */
63      protected double imaginary;
64      
65      /** 
66       * The real part 
67       * @deprecated to be made final and private in 2.0
68       */
69      protected double real;
70      
71      /**
72       * Create a complex number given the real and imaginary parts.
73       *
74       * @param real the real part
75       * @param imaginary the imaginary part
76       */
77      public Complex(double real, double imaginary) {
78          super();
79          this.real = real;
80          this.imaginary = imaginary;
81      }
82  
83      /**
84       * Return the absolute value of this complex number.
85       * <p>
86       * Returns <code>NaN</code> if either real or imaginary part is
87       * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
88       * neither part is <code>NaN</code>, but at least one part takes an infinite
89       * value.</p>
90       *
91       * @return the absolute value
92       */
93      public double abs() {
94          if (isNaN()) {
95              return Double.NaN;
96          }
97          
98          if (isInfinite()) {
99              return Double.POSITIVE_INFINITY;
100         }
101         
102         if (Math.abs(real) < Math.abs(imaginary)) {
103             if (imaginary == 0.0) {
104                 return Math.abs(real);
105             }
106             double q = real / imaginary;
107             return (Math.abs(imaginary) * Math.sqrt(1 + q*q));
108         } else {
109             if (real == 0.0) {
110                 return Math.abs(imaginary);
111             }
112             double q = imaginary / real;
113             return (Math.abs(real) * Math.sqrt(1 + q*q));
114         }
115     }
116     
117     /**
118      * Return the sum of this complex number and the given complex number.
119      * <p>
120      * Uses the definitional formula 
121      * <pre>
122      * (a + bi) + (c + di) = (a+c) + (b+d)i
123      * </pre></p>
124      * <p>
125      * If either this or <code>rhs</code> has a NaN value in either part,
126      * {@link #NaN} is returned; otherwise Inifinite and NaN values are
127      * returned in the parts of the result according to the rules for
128      * {@link java.lang.Double} arithmetic.</p> 
129      *
130      * @param rhs the other complex number
131      * @return the complex number sum
132      * @throws NullPointerException if <code>rhs</code> is null
133      */
134     public Complex add(Complex rhs) {   
135         return createComplex(real + rhs.getReal(),
136             imaginary + rhs.getImaginary());
137     }
138     
139     /**
140      * Return the conjugate of this complex number. The conjugate of
141      * "A + Bi" is "A - Bi". 
142      * <p>
143      * {@link #NaN} is returned if either the real or imaginary
144      * part of this Complex number equals <code>Double.NaN</code>.</p>
145      * <p>
146      * If the imaginary part is infinite, and the real part is not NaN, 
147      * the returned value has infinite imaginary part of the opposite
148      * sign - e.g. the conjugate of <code>1 + POSITIVE_INFINITY i</code>
149      * is <code>1 - NEGATIVE_INFINITY i</code></p>
150      *
151      * @return the conjugate of this Complex object
152      */
153     public Complex conjugate() {
154         if (isNaN()) {
155             return NaN;
156         }   
157         return createComplex(real, -imaginary);
158     }
159     
160     /**
161      * Return the quotient of this complex number and the given complex number.
162      * <p>
163      * Implements the definitional formula
164      * <pre><code>
165      *    a + bi          ac + bd + (bc - ad)i
166      *    ----------- = -------------------------
167      *    c + di               c<sup>2</sup> + d<sup>2</sup>
168      * </code></pre>
169      * but uses 
170      * <a href="http://doi.acm.org/10.1145/1039813.1039814">
171      * prescaling of operands</a> to limit the effects of overflows and
172      * underflows in the computation.</p>
173      * <p>
174      * Infinite and NaN values are handled / returned according to the
175      * following rules, applied in the order presented:
176      * <ul>
177      * <li>If either this or <code>rhs</code> has a NaN value in either part,
178      *  {@link #NaN} is returned.</li>
179      * <li>If <code>rhs</code> equals {@link #ZERO}, {@link #NaN} is returned.
180      * </li>
181      * <li>If this and <code>rhs</code> are both infinite,
182      * {@link #NaN} is returned.</li>
183      * <li>If this is finite (i.e., has no infinite or NaN parts) and
184      *  <code>rhs</code> is infinite (one or both parts infinite), 
185      * {@link #ZERO} is returned.</li>
186      * <li>If this is infinite and <code>rhs</code> is finite, NaN values are
187      * returned in the parts of the result if the {@link java.lang.Double}
188      * rules applied to the definitional formula force NaN results.</li>
189      * </ul></p>
190      * 
191      * @param rhs the other complex number
192      * @return the complex number quotient
193      * @throws NullPointerException if <code>rhs</code> is null
194      */
195     public Complex divide(Complex rhs) {
196         if (isNaN() || rhs.isNaN()) {
197             return NaN;
198         }
199 
200         double c = rhs.getReal();
201         double d = rhs.getImaginary();
202         if (c == 0.0 && d == 0.0) {
203             return NaN;
204         }
205         
206         if (rhs.isInfinite() && !isInfinite()) {
207             return ZERO;
208         }
209 
210         if (Math.abs(c) < Math.abs(d)) {
211             if (d == 0.0) {
212                 return createComplex(real/c, imaginary/c);
213             }
214             double q = c / d;
215             double denominator = c * q + d;
216             return createComplex((real * q + imaginary) / denominator,
217                 (imaginary * q - real) / denominator);
218         } else {
219             if (c == 0.0) {
220                 return createComplex(imaginary/d, -real/c);
221             }
222             double q = d / c;
223             double denominator = d * q + c;
224             return createComplex((imaginary * q + real) / denominator,
225                 (imaginary - real * q) / denominator);
226         }
227     }
228     
229     /**
230      * Test for the equality of two Complex objects.
231      * <p>
232      * If both the real and imaginary parts of two Complex numbers
233      * are exactly the same, and neither is <code>Double.NaN</code>, the two
234      * Complex objects are considered to be equal.</p>
235      * <p>
236      * All <code>NaN</code> values are considered to be equal - i.e, if either
237      * (or both) real and imaginary parts of the complex number are equal
238      * to <code>Double.NaN</code>, the complex number is equal to 
239      * <code>Complex.NaN</code>.</p>
240      *
241      * @param other Object to test for equality to this
242      * @return true if two Complex objects are equal, false if
243      *         object is null, not an instance of Complex, or
244      *         not equal to this Complex instance
245      * 
246      */
247     public boolean equals(Object other) {
248         boolean ret;
249         
250         if (this == other) { 
251             ret = true;
252         } else if (other == null) {
253             ret = false;
254         } else  {
255             try {
256                 Complex rhs = (Complex)other;
257                 if (rhs.isNaN()) {
258                     ret = this.isNaN();
259                 } else {
260                 ret = (Double.doubleToRawLongBits(real) ==
261                         Double.doubleToRawLongBits(rhs.getReal())) &&
262                     (Double.doubleToRawLongBits(imaginary) ==
263                         Double.doubleToRawLongBits(rhs.getImaginary())); 
264                 }
265             } catch (ClassCastException ex) {
266                 // ignore exception
267                 ret = false;
268             }
269         }
270       
271         return ret;
272     }
273     
274     /**
275      * Get a hashCode for the complex number.
276      * <p>
277      * All NaN values have the same hash code.</p>
278      * 
279      * @return a hash code value for this object
280      */
281     public int hashCode() {
282         if (isNaN()) {
283             return 7;
284         }
285         return 37 * (17 * MathUtils.hash(imaginary) + 
286             MathUtils.hash(real));
287     }
288 
289     /**
290      * Access the imaginary part.
291      *
292      * @return the imaginary part
293      */
294     public double getImaginary() {
295         return imaginary;
296     }
297 
298     /**
299      * Access the real part.
300      *
301      * @return the real part
302      */
303     public double getReal() {
304         return real;
305     }
306     
307     /**
308      * Returns true if either or both parts of this complex number is NaN;
309      * false otherwise
310      *
311      * @return  true if either or both parts of this complex number is NaN;
312      * false otherwise
313      */
314     public boolean isNaN() {
315         return Double.isNaN(real) || Double.isNaN(imaginary);        
316     }
317     
318     /**
319      * Returns true if either the real or imaginary part of this complex number
320      * takes an infinite value (either <code>Double.POSITIVE_INFINITY</code> or 
321      * <code>Double.NEGATIVE_INFINITY</code>) and neither part
322      * is <code>NaN</code>.
323      * 
324      * @return true if one or both parts of this complex number are infinite
325      * and neither part is <code>NaN</code>
326      */
327     public boolean isInfinite() {
328         return !isNaN() && 
329         (Double.isInfinite(real) || Double.isInfinite(imaginary));        
330     }
331     
332     /**
333      * Return the product of this complex number and the given complex number.
334      * <p>
335      * Implements preliminary checks for NaN and infinity followed by
336      * the definitional formula:
337      * <pre><code>
338      * (a + bi)(c + di) = (ac - bd) + (ad + bc)i
339      * </code></pre>
340      * </p>
341      * <p>
342      * Returns {@link #NaN} if either this or <code>rhs</code> has one or more
343      * NaN parts.
344      * </p>
345      * Returns {@link #INF} if neither this nor <code>rhs</code> has one or more
346      * NaN parts and if either this or <code>rhs</code> has one or more
347      * infinite parts (same result is returned regardless of the sign of the
348      * components).
349      * </p>
350      * <p>
351      * Returns finite values in components of the result per the
352      * definitional formula in all remaining cases.
353      *  </p>
354      * 
355      * @param rhs the other complex number
356      * @return the complex number product
357      * @throws NullPointerException if <code>rhs</code> is null
358      */
359     public Complex multiply(Complex rhs) {
360         if (isNaN() || rhs.isNaN()) {
361             return NaN;
362         }
363         if (Double.isInfinite(real) || Double.isInfinite(imaginary) ||
364             Double.isInfinite(rhs.real)|| Double.isInfinite(rhs.imaginary)) {
365             // we don't use Complex.isInfinite() to avoid testing for NaN again
366             return INF;
367         }
368         return createComplex(real * rhs.real - imaginary * rhs.imaginary,
369                 real * rhs.imaginary + imaginary * rhs.real);
370     }
371     
372     /**
373      * Return the additive inverse of this complex number.
374      * <p>
375      * Returns <code>Complex.NaN</code> if either real or imaginary
376      * part of this Complex number equals <code>Double.NaN</code>.</p>
377      *
378      * @return the negation of this complex number
379      */
380     public Complex negate() {
381         if (isNaN()) {
382             return NaN;
383         }
384         
385         return createComplex(-real, -imaginary);
386     }
387     
388     /**
389      * Return the difference between this complex number and the given complex
390      * number.
391       * <p>
392      * Uses the definitional formula 
393      * <pre>
394      * (a + bi) - (c + di) = (a-c) + (b-d)i
395      * </pre></p>
396      * <p>
397      * If either this or <code>rhs</code> has a NaN value in either part,
398      * {@link #NaN} is returned; otherwise inifinite and NaN values are
399      * returned in the parts of the result according to the rules for
400      * {@link java.lang.Double} arithmetic. </p>
401      * 
402      * @param rhs the other complex number
403      * @return the complex number difference
404      * @throws NullPointerException if <code>rhs</code> is null
405      */
406     public Complex subtract(Complex rhs) {
407         if (isNaN() || rhs.isNaN()) {
408             return NaN;
409         }
410         
411         return createComplex(real - rhs.getReal(),
412             imaginary - rhs.getImaginary());
413     }
414     
415     /**
416      * Compute the 
417      * <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
418      * inverse cosine</a> of this complex number.
419      * <p>
420      * Implements the formula: <pre>
421      * <code> acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))</code></pre></p>
422      * <p>
423      * Returns {@link Complex#NaN} if either real or imaginary part of the 
424      * input argument is <code>NaN</code> or infinite.</p>
425      * 
426      * @return the inverse cosine of this complex number
427      * @since 1.2
428      */
429     public Complex acos() {
430         if (isNaN()) {
431             return Complex.NaN;
432         }
433 
434         return this.add(this.sqrt1z().multiply(Complex.I)).log()
435               .multiply(Complex.I.negate());
436     }
437     
438     /**
439      * Compute the 
440      * <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
441      * inverse sine</a> of this complex number.
442      * <p>
443      * Implements the formula: <pre>
444      * <code> asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz)) </code></pre></p>
445      * <p>
446      * Returns {@link Complex#NaN} if either real or imaginary part of the 
447      * input argument is <code>NaN</code> or infinite.</p>
448      * 
449      * @return the inverse sine of this complex number.
450      * @since 1.2
451      */
452     public Complex asin() {
453         if (isNaN()) {
454             return Complex.NaN;
455         }
456 
457         return sqrt1z().add(this.multiply(Complex.I)).log()
458               .multiply(Complex.I.negate());
459     }
460     
461     /**
462      * Compute the 
463      * <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
464      * inverse tangent</a> of this complex number.
465      * <p>
466      * Implements the formula: <pre>
467      * <code> atan(z) = (i/2) log((i + z)/(i - z)) </code></pre></p>
468      * <p>
469      * Returns {@link Complex#NaN} if either real or imaginary part of the 
470      * input argument is <code>NaN</code> or infinite.</p>
471      * 
472      * @return the inverse tangent of this complex number
473      * @since 1.2
474      */
475     public Complex atan() {
476         if (isNaN()) {
477             return Complex.NaN;
478         }
479         
480         return this.add(Complex.I).divide(Complex.I.subtract(this)).log()
481             .multiply(Complex.I.divide(createComplex(2.0, 0.0)));
482     }
483     
484     /**
485      * Compute the 
486      * <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
487      * cosine</a>
488      * of this complex number.
489      * <p>
490      * Implements the formula: <pre>
491      * <code> cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i</code></pre>
492      * where the (real) functions on the right-hand side are
493      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
494      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
495      * <p>
496      * Returns {@link Complex#NaN} if either real or imaginary part of the 
497      * input argument is <code>NaN</code>.</p>
498      * <p>
499      * Infinite values in real or imaginary parts of the input may result in
500      * infinite or NaN values returned in parts of the result.<pre>
501      * Examples: 
502      * <code>
503      * cos(1 &plusmn; INFINITY i) = 1 &#x2213; INFINITY i
504      * cos(&plusmn;INFINITY + i) = NaN + NaN i
505      * cos(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
506      * 
507      * @return the cosine of this complex number
508      * @since 1.2
509      */
510     public Complex cos() {
511         if (isNaN()) {
512             return Complex.NaN;
513         }
514         
515         return createComplex(Math.cos(real) * MathUtils.cosh(imaginary),
516             -Math.sin(real) * MathUtils.sinh(imaginary));
517     }
518     
519     /**
520      * Compute the 
521      * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
522      * hyperbolic cosine</a> of this complex number.
523      * <p>
524      * Implements the formula: <pre>
525      * <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
526      * where the (real) functions on the right-hand side are
527      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
528      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
529      * <p>
530      * Returns {@link Complex#NaN} if either real or imaginary part of the 
531      * input argument is <code>NaN</code>.</p>
532      * <p>
533      * Infinite values in real or imaginary parts of the input may result in
534      * infinite or NaN values returned in parts of the result.<pre>
535      * Examples: 
536      * <code>
537      * cosh(1 &plusmn; INFINITY i) = NaN + NaN i
538      * cosh(&plusmn;INFINITY + i) = INFINITY &plusmn; INFINITY i
539      * cosh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
540      * 
541      * @return the hyperbolic cosine of this complex number.
542      * @since 1.2
543      */
544     public Complex cosh() {
545         if (isNaN()) {
546             return Complex.NaN;
547         }
548         
549         return createComplex(MathUtils.cosh(real) * Math.cos(imaginary),
550             MathUtils.sinh(real) * Math.sin(imaginary));
551     }
552     
553     /**
554      * Compute the
555      * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
556      * exponential function</a> of this complex number.
557      * <p>
558      * Implements the formula: <pre>
559      * <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
560      * where the (real) functions on the right-hand side are
561      * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
562      * {@link java.lang.Math#sin}.</p>
563      * <p>
564      * Returns {@link Complex#NaN} if either real or imaginary part of the 
565      * input argument is <code>NaN</code>.</p>
566      * <p>
567      * Infinite values in real or imaginary parts of the input may result in
568      * infinite or NaN values returned in parts of the result.<pre>
569      * Examples: 
570      * <code>
571      * exp(1 &plusmn; INFINITY i) = NaN + NaN i
572      * exp(INFINITY + i) = INFINITY + INFINITY i
573      * exp(-INFINITY + i) = 0 + 0i
574      * exp(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
575      * 
576      * @return <i>e</i><sup><code>this</code></sup>
577      * @since 1.2
578      */
579     public Complex exp() {
580         if (isNaN()) {
581             return Complex.NaN;
582         }
583         
584         double expReal = Math.exp(real);
585         return createComplex(expReal *  Math.cos(imaginary), expReal * Math.sin(imaginary));
586     }
587     
588     /**
589      * Compute the 
590      * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
591      * natural logarithm</a> of this complex number.
592      * <p>
593      * Implements the formula: <pre>
594      * <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
595      * where ln on the right hand side is {@link java.lang.Math#log},
596      * <code>|a + bi|</code> is the modulus, {@link Complex#abs},  and
597      * <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code></p>
598      * <p>
599      * Returns {@link Complex#NaN} if either real or imaginary part of the 
600      * input argument is <code>NaN</code>.</p>
601      * <p>
602      * Infinite (or critical) values in real or imaginary parts of the input may
603      * result in infinite or NaN values returned in parts of the result.<pre>
604      * Examples: 
605      * <code>
606      * log(1 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
607      * log(INFINITY + i) = INFINITY + 0i
608      * log(-INFINITY + i) = INFINITY + &pi;i
609      * log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
610      * log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/4)i
611      * log(0 + 0i) = -INFINITY + 0i
612      * </code></pre></p>
613      * 
614      * @return ln of this complex number.
615      * @since 1.2
616      */
617     public Complex log() {
618         if (isNaN()) {
619             return Complex.NaN;
620         }
621 
622         return createComplex(Math.log(abs()),
623             Math.atan2(imaginary, real));        
624     }
625     
626     /**
627      * Returns of value of this complex number raised to the power of <code>x</code>.
628      * <p>
629      * Implements the formula: <pre>
630      * <code> y<sup>x</sup> = exp(x&middot;log(y))</code></pre> 
631      * where <code>exp</code> and <code>log</code> are {@link #exp} and
632      * {@link #log}, respectively.</p>
633      * <p>
634      * Returns {@link Complex#NaN} if either real or imaginary part of the 
635      * input argument is <code>NaN</code> or infinite, or if <code>y</code>
636      * equals {@link Complex#ZERO}.</p>
637      * 
638      * @param x the exponent.
639      * @return <code>this</code><sup><code>x</code></sup>
640      * @throws NullPointerException if x is null
641      * @since 1.2
642      */
643     public Complex pow(Complex x) {
644         if (x == null) {
645             throw new NullPointerException();
646         }
647         return this.log().multiply(x).exp();
648     }
649     
650     /**
651      * Compute the 
652      * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
653      * sine</a>
654      * of this complex number.
655      * <p>
656      * Implements the formula: <pre>
657      * <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
658      * where the (real) functions on the right-hand side are
659      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
660      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
661      * <p>
662      * Returns {@link Complex#NaN} if either real or imaginary part of the 
663      * input argument is <code>NaN</code>.</p>
664      * <p>
665      * Infinite values in real or imaginary parts of the input may result in
666      * infinite or NaN values returned in parts of the result.<pre>
667      * Examples: 
668      * <code>
669      * sin(1 &plusmn; INFINITY i) = 1 &plusmn; INFINITY i
670      * sin(&plusmn;INFINITY + i) = NaN + NaN i
671      * sin(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
672      * 
673      * @return the sine of this complex number.
674      * @since 1.2
675      */
676     public Complex sin() {
677         if (isNaN()) {
678             return Complex.NaN;
679         }
680         
681         return createComplex(Math.sin(real) * MathUtils.cosh(imaginary),
682             Math.cos(real) * MathUtils.sinh(imaginary));
683     }
684     
685     /**
686      * Compute the 
687      * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
688      * hyperbolic sine</a> of this complex number.
689      * <p>
690      * Implements the formula: <pre>
691      * <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
692      * where the (real) functions on the right-hand side are
693      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
694      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
695      * <p>
696      * Returns {@link Complex#NaN} if either real or imaginary part of the 
697      * input argument is <code>NaN</code>.</p>
698      * <p>
699      * Infinite values in real or imaginary parts of the input may result in
700      * infinite or NaN values returned in parts of the result.<pre>
701      * Examples: 
702      * <code>
703      * sinh(1 &plusmn; INFINITY i) = NaN + NaN i
704      * sinh(&plusmn;INFINITY + i) = &plusmn; INFINITY + INFINITY i
705      * sinh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
706      * 
707      * @return the hyperbolic sine of this complex number
708      * @since 1.2
709      */
710     public Complex sinh() {
711         if (isNaN()) {
712             return Complex.NaN;
713         }
714         
715         return createComplex(MathUtils.sinh(real) * Math.cos(imaginary),
716             MathUtils.cosh(real) * Math.sin(imaginary));
717     }
718     
719     /**
720      * Compute the 
721      * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
722      * square root</a> of this complex number.
723      * <p>
724      * Implements the following algorithm to compute <code>sqrt(a + bi)</code>: 
725      * <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
726      * <li><pre>if <code> a &#8805; 0</code> return <code>t + (b/2t)i</code>
727      *  else return <code>|b|/2t + sign(b)t i </code></pre></li>
728      * </ol>
729      * where <ul>
730      * <li><code>|a| = {@link Math#abs}(a)</code></li>
731      * <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
732      * <li><code>sign(b) =  {@link MathUtils#indicator}(b) </code>
733      * </ul></p>
734      * <p>
735      * Returns {@link Complex#NaN} if either real or imaginary part of the 
736      * input argument is <code>NaN</code>.</p>
737      * <p>
738      * Infinite values in real or imaginary parts of the input may result in
739      * infinite or NaN values returned in parts of the result.<pre>
740      * Examples: 
741      * <code>
742      * sqrt(1 &plusmn; INFINITY i) = INFINITY + NaN i
743      * sqrt(INFINITY + i) = INFINITY + 0i
744      * sqrt(-INFINITY + i) = 0 + INFINITY i
745      * sqrt(INFINITY &plusmn; INFINITY i) = INFINITY + NaN i
746      * sqrt(-INFINITY &plusmn; INFINITY i) = NaN &plusmn; INFINITY i
747      * </code></pre></p>
748      * 
749      * @return the square root of this complex number
750      * @since 1.2
751      */
752     public Complex sqrt() {
753         if (isNaN()) {
754             return Complex.NaN;
755         }
756         
757         if (real == 0.0 && imaginary == 0.0) {
758             return createComplex(0.0, 0.0);
759         }
760         
761         double t = Math.sqrt((Math.abs(real) + abs()) / 2.0);
762         if (real >= 0.0) {
763             return createComplex(t, imaginary / (2.0 * t));
764         } else {
765             return createComplex(Math.abs(imaginary) / (2.0 * t),
766                 MathUtils.indicator(imaginary) * t);
767         }
768     }
769     
770     /**
771      * Compute the 
772      * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
773      * square root</a> of 1 - <code>this</code><sup>2</sup> for this complex
774      * number.
775      * <p>
776      * Computes the result directly as 
777      * <code>sqrt(Complex.ONE.subtract(z.multiply(z)))</code>.</p>
778      * <p>
779      * Returns {@link Complex#NaN} if either real or imaginary part of the 
780      * input argument is <code>NaN</code>.</p>
781      * <p>
782      * Infinite values in real or imaginary parts of the input may result in
783      * infinite or NaN values returned in parts of the result.</p>
784      * 
785      * @return the square root of 1 - <code>this</code><sup>2</sup>
786      * @since 1.2
787      */
788     public Complex sqrt1z() {
789         return createComplex(1.0, 0.0).subtract(this.multiply(this)).sqrt();
790     }
791     
792     /**
793      * Compute the 
794      * <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
795      * tangent</a> of this complex number.
796      * <p>
797      * Implements the formula: <pre>
798      * <code>tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i</code></pre>
799      * where the (real) functions on the right-hand side are
800      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
801      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
802      * <p>
803      * Returns {@link Complex#NaN} if either real or imaginary part of the 
804      * input argument is <code>NaN</code>.</p>
805      * <p>
806      * Infinite (or critical) values in real or imaginary parts of the input may
807      * result in infinite or NaN values returned in parts of the result.<pre>
808      * Examples: 
809      * <code>
810      * tan(1 &plusmn; INFINITY i) = 0 + NaN i
811      * tan(&plusmn;INFINITY + i) = NaN + NaN i
812      * tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
813      * tan(&plusmn;&pi;/2 + 0 i) = &plusmn;INFINITY + NaN i</code></pre></p>
814      * 
815      * @return the tangent of this complex number
816      * @since 1.2
817      */
818     public Complex tan() {
819         if (isNaN()) {
820             return Complex.NaN;
821         }
822         
823         double real2 = 2.0 * real;
824         double imaginary2 = 2.0 * imaginary;
825         double d = Math.cos(real2) + MathUtils.cosh(imaginary2);
826         
827         return createComplex(Math.sin(real2) / d, MathUtils.sinh(imaginary2) / d);
828     }
829     
830     /**
831      * Compute the
832      * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
833      * hyperbolic tangent</a> of this complex number.
834      * <p>
835      * Implements the formula: <pre>
836      * <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i</code></pre>
837      * where the (real) functions on the right-hand side are
838      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, 
839      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
840      * <p>
841      * Returns {@link Complex#NaN} if either real or imaginary part of the 
842      * input argument is <code>NaN</code>.</p>
843      * <p>
844      * Infinite values in real or imaginary parts of the input may result in
845      * infinite or NaN values returned in parts of the result.<pre>
846      * Examples: 
847      * <code>
848      * tanh(1 &plusmn; INFINITY i) = NaN + NaN i
849      * tanh(&plusmn;INFINITY + i) = NaN + 0 i
850      * tanh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
851      * tanh(0 + (&pi;/2)i) = NaN + INFINITY i</code></pre></p>
852      *
853      * @return the hyperbolic tangent of this complex number
854      * @since 1.2
855      */
856     public Complex tanh() {
857         if (isNaN()) {
858             return Complex.NaN;
859         }
860         
861         double real2 = 2.0 * real;
862         double imaginary2 = 2.0 * imaginary;
863         double d = MathUtils.cosh(real2) + Math.cos(imaginary2);
864         
865         return createComplex(MathUtils.sinh(real2) / d, Math.sin(imaginary2) / d);
866     }
867 
868     /**
869      * Create a complex number given the real and imaginary parts.
870      *
871      * @param real the real part
872      * @param imaginary the imaginary part
873      * @return a new complex number instance
874      * @since 1.2
875      */
876     protected Complex createComplex(double real, double imaginary) {
877         return new Complex(real, imaginary);
878     }
879 }