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 org.apache.commons.math.util.MathUtils;
    20
    21  /***
    22   * Static implementations of common
    23   * {@link org.apache.commons.math.complex.Complex}-valued functions.  Included
    24   * are trigonometric, exponential, log, power and square root functions.
    25   *<p>
    26   * Reference:
    27   * <ul>
    28   * <li><a href="http://myweb.lmu.edu/dmsmith/ZMLIB.pdf">
    29   * Multiple Precision Complex Arithmetic and Functions</a></li>
    30   * </ul>
    31   * See individual method javadocs for the computational formulas used.
    32   * In general, NaN values in either real or imaginary parts of input arguments
    33   * result in {@link Complex#NaN} returned.  Otherwise, infinite or NaN values
    34   * are returned as they arise in computing the real functions specified in the
    35   * computational formulas.  Null arguments result in NullPointerExceptions.
    36   *
    37   * @version $Revision: 349387 $ $Date: 2005-11-27 23:15:46 -0700 (Sun, 27 Nov 2005) $
    38   */
    39  public class ComplexUtils {
    40
    41      /***
    42       * Default constructor.
    43       */
    44      private ComplexUtils() {
    45          super();
    46      }
    47
    48      /***
    49       * Compute the
    50       * <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
    51       * inverse cosine</a> for the given complex argument.
    52       * <p>
    53       * Implements the formula: <pre>
    54       * <code> acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))</code></pre>
    55       * <p>
    56       * Returns {@link Complex#NaN} if either real or imaginary part of the
    57       * input argument is <code>NaN</code> or infinite.
    58       *
    59       * @param z the value whose inverse cosine is to be returned
    60       * @return the inverse cosine of <code>z</code>
    61       * @throws NullPointerException if <code>z</code> is null
    62       */
    63      public static Complex acos(Complex z) {
    64          if (z.isNaN()) {
    65              return Complex.NaN;
    66          }
    67
    68          return Complex.I.negate().multiply(log(z.add(
    69              Complex.I.multiply(sqrt1z(z)))));
    70      }
    71
    72      /***
    73       * Compute the
    74       * <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
    75       * inverse sine</a> for the given complex argument.
    76       * <p>
    77       * Implements the formula: <pre>
    78       * <code> asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz)) </code></pre>
    79       * <p>
    80       * Returns {@link Complex#NaN} if either real or imaginary part of the
    81       * input argument is <code>NaN</code> or infinite.
    82       *
    83       * @param z the value whose inverse sine is to be returned.
    84       * @return the inverse sine of <code>z</code>.
    85       * @throws NullPointerException if <code>z</code> is null
    86       */
    87      public static Complex asin(Complex z) {
    88          if (z.isNaN()) {
    89              return Complex.NaN;
    90          }
    91
    92          return Complex.I.negate().multiply(log(sqrt1z(z).add(
    93              Complex.I.multiply(z))));
    94      }
    95
    96      /***
    97       * Compute the
    98       * <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
    99       * inverse tangent</a> for the given complex argument.
    100      * <p>
    101      * Implements the formula: <pre>
    102      * <code> atan(z) = (i/2) log((i + z)/(i - z)) </code></pre>
    103      * <p>
    104      * Returns {@link Complex#NaN} if either real or imaginary part of the
    105      * input argument is <code>NaN</code> or infinite.
    106      *
    107      * @param z the value whose inverse tangent is to be returned
    108      * @return the inverse tangent of <code>z</code>
    109      * @throws NullPointerException if <code>z</code> is null
    110      */
    111     public static Complex atan(Complex z) {
    112         if (z.isNaN()) {
    113             return Complex.NaN;
    114         }
    115
    116         return Complex.I.multiply(
    117             log(Complex.I.add(z).divide(Complex.I.subtract(z))))
    118             .divide(new Complex(2.0, 0.0));
    119     }
    120
    121     /***
    122      * Compute the
    123      * <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
    124      * cosine</a>
    125      * for the given complex argument.
    126      * <p>
    127      * Implements the formula: <pre>
    128      * <code> cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i</code></pre>
    129      * where the (real) functions on the right-hand side are
    130      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    131      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
    132      * <p>
    133      * Returns {@link Complex#NaN} if either real or imaginary part of the
    134      * input argument is <code>NaN</code>.
    135      * <p>
    136      * Infinite values in real or imaginary parts of the input may result in
    137      * infinite or NaN values returned in parts of the result.<pre>
    138      * Examples:
    139      * <code>
    140      * cos(1 &plusmn; INFINITY i) = 1 &#x2213; INFINITY i
    141      * cos(&plusmn;INFINITY + i) = NaN + NaN i
    142      * cos(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
    143      *
    144      * @param z the value whose cosine is to be returned
    145      * @return the cosine of <code>z</code>
    146      * @throws NullPointerException if <code>z</code> is null
    147      */
    148     public static Complex cos(Complex z) {
    149         if (z.isNaN()) {
    150             return Complex.NaN;
    151         }
    152
    153         double a = z.getReal();
    154         double b = z.getImaginary();
    155
    156         return new Complex(Math.cos(a) * MathUtils.cosh(b),
    157             -Math.sin(a) * MathUtils.sinh(b));
    158     }
    159
    160     /***
    161      * Compute the
    162      * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
    163      * hyperbolic cosine</a> for the given complex argument.
    164      * <p>
    165      * Implements the formula: <pre>
    166      * <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
    167      * where the (real) functions on the right-hand side are
    168      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    169      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
    170      * <p>
    171      * Returns {@link Complex#NaN} if either real or imaginary part of the
    172      * input argument is <code>NaN</code>.
    173      * <p>
    174      * Infinite values in real or imaginary parts of the input may result in
    175      * infinite or NaN values returned in parts of the result.<pre>
    176      * Examples:
    177      * <code>
    178      * cosh(1 &plusmn; INFINITY i) = NaN + NaN i
    179      * cosh(&plusmn;INFINITY + i) = INFINITY &plusmn; INFINITY i
    180      * cosh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
    181      * <p>
    182      * Throws <code>NullPointerException</code> if z is null.
    183      *
    184      * @param z the value whose hyperbolic cosine is to be returned.
    185      * @return the hyperbolic cosine of <code>z</code>.
    186      */
    187     public static Complex cosh(Complex z) {
    188         if (z.isNaN()) {
    189             return Complex.NaN;
    190         }
    191
    192         double a = z.getReal();
    193         double b = z.getImaginary();
    194
    195         return new Complex(MathUtils.cosh(a) * Math.cos(b),
    196             MathUtils.sinh(a) * Math.sin(b));
    197     }
    198
    199     /***
    200      * Compute the
    201      * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
    202      * exponential function</a> for the given complex argument.
    203      * <p>
    204      * Implements the formula: <pre>
    205      * <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
    206      * where the (real) functions on the right-hand side are
    207      * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
    208      * {@link java.lang.Math#sin}.
    209      * <p>
    210      * Returns {@link Complex#NaN} if either real or imaginary part of the
    211      * input argument is <code>NaN</code>.
    212      * <p>
    213      * Infinite values in real or imaginary parts of the input may result in
    214      * infinite or NaN values returned in parts of the result.<pre>
    215      * Examples:
    216      * <code>
    217      * exp(1 &plusmn; INFINITY i) = NaN + NaN i
    218      * exp(INFINITY + i) = INFINITY + INFINITY i
    219      * exp(-INFINITY + i) = 0 + 0i
    220      * exp(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
    221      * <p>
    222      * Throws <code>NullPointerException</code> if z is null.
    223      *
    224      * @param z the value
    225      * @return <i>e</i><sup><code>z</code></sup>
    226      */
    227     public static Complex exp(Complex z) {
    228         if (z.isNaN()) {
    229             return Complex.NaN;
    230         }
    231
    232         double b = z.getImaginary();
    233         double expA = Math.exp(z.getReal());
    234         return new Complex(expA *  Math.cos(b), expA * Math.sin(b));
    235     }
    236
    237     /***
    238      * Compute the
    239      * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
    240      * natural logarithm</a> for the given complex argument.
    241      * <p>
    242      * Implements the formula: <pre>
    243      * <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
    244      * where ln on the right hand side is {@link java.lang.Math#log},
    245      * <code>|a + bi|</code> is the modulus, {@link Complex#abs},  and
    246      * <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code>
    247      * <p>
    248      * Returns {@link Complex#NaN} if either real or imaginary part of the
    249      * input argument is <code>NaN</code>.
    250      * <p>
    251      * Infinite (or critical) values in real or imaginary parts of the input may
    252      * result in infinite or NaN values returned in parts of the result.<pre>
    253      * Examples:
    254      * <code>
    255      * log(1 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
    256      * log(INFINITY + i) = INFINITY + 0i
    257      * log(-INFINITY + i) = INFINITY + &pi;i
    258      * log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
    259      * log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/4)i
    260      * log(0 + 0i) = -INFINITY + 0i
    261      * </code></pre>
    262      * Throws <code>NullPointerException</code> if z is null.
    263      *
    264      * @param z the value.
    265      * @return ln <code>z</code>.
    266      */
    267     public static Complex log(Complex z) {
    268         if (z.isNaN()) {
    269             return Complex.NaN;
    270         }
    271
    272         return new Complex(Math.log(z.abs()),
    273             Math.atan2(z.getImaginary(), z.getReal()));
    274     }
    275
    276     /***
    277      * Creates a complex number from the given polar representation.
    278      * <p>
    279      * The value returned is <code>r&middot;e<sup>i&middot;theta</sup></code>,
    280      * computed as <code>r&middot;cos(theta) + r&middot;sin(theta)i</code>
    281      * <p>
    282      * If either <code>r</code> or <code>theta</code> is NaN, or
    283      * <code>theta</code> is infinite, {@link Complex#NaN} is returned.
    284      * <p>
    285      * If <code>r</code> is infinite and <code>theta</code> is finite,
    286      * infinite or NaN values may be returned in parts of the result, following
    287      * the rules for double arithmetic.<pre>
    288      * Examples:
    289      * <code>
    290      * polar2Complex(INFINITY, &pi;/4) = INFINITY + INFINITY i
    291      * polar2Complex(INFINITY, 0) = INFINITY + NaN i
    292      * polar2Complex(INFINITY, -&pi;/4) = INFINITY - INFINITY i
    293      * polar2Complex(INFINITY, 5&pi;/4) = -INFINITY - INFINITY i </code></pre>
    294      *
    295      * @param r the modulus of the complex number to create
    296      * @param theta  the argument of the complex number to create
    297      * @return <code>r&middot;e<sup>i&middot;theta</sup></code>
    298      * @throws IllegalArgumentException  if r is negative
    299      * @since 1.1
    300      */
    301     public static Complex polar2Complex(double r, double theta) {
    302         if (r < 0) {
    303             throw new IllegalArgumentException
    304                 ("Complex modulus must not be negative");
    305         }
    306         return new Complex(r * Math.cos(theta), r * Math.sin(theta));
    307     }
    308
    309     /***
    310      * Returns of value of <code>y</code> raised to the power of <code>x</code>.
    311      * <p>
    312      * Implements the formula: <pre>
    313      * <code> y<sup>x</sup> = exp(x&middot;log(y))</code></pre>
    314      * where <code>exp</code> and <code>log</code> are {@link #exp} and
    315      * {@link #log}, respectively.
    316      * <p>
    317      * Returns {@link Complex#NaN} if either real or imaginary part of the
    318      * input argument is <code>NaN</code> or infinite, or if <code>y</code>
    319      * equals {@link Complex#ZERO}.
    320      *
    321      * @param y the base.
    322      * @param x the exponent.
    323      * @return <code>y</code><sup><code>x</code></sup>
    324      * @throws NullPointerException if either x or y is null
    325      */
    326     public static Complex pow(Complex y, Complex x) {
    327         return exp(x.multiply(log(y)));
    328     }
    329
    330     /***
    331      * Compute the
    332      * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
    333      * sine</a>
    334      * for the given complex argument.
    335      * <p>
    336       * Implements the formula: <pre>
    337      * <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
    338      * where the (real) functions on the right-hand side are
    339      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    340      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
    341      * <p>
    342      * Returns {@link Complex#NaN} if either real or imaginary part of the
    343      * input argument is <code>NaN</code>.
    344      * <p>
    345      * Infinite values in real or imaginary parts of the input may result in
    346      * infinite or NaN values returned in parts of the result.<pre>
    347      * Examples:
    348      * <code>
    349      * sin(1 &plusmn; INFINITY i) = 1 &plusmn; INFINITY i
    350      * sin(&plusmn;INFINITY + i) = NaN + NaN i
    351      * sin(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre>
    352      *
    353      * Throws <code>NullPointerException</code> if z is null.
    354      *
    355      * @param z the value whose sine is to be returned.
    356      * @return the sine of <code>z</code>.
    357      */
    358     public static Complex sin(Complex z) {
    359         if (z.isNaN()) {
    360             return Complex.NaN;
    361         }
    362
    363         double a = z.getReal();
    364         double b = z.getImaginary();
    365
    366         return new Complex(Math.sin(a) * MathUtils.cosh(b),
    367             Math.cos(a) * MathUtils.sinh(b));
    368     }
    369
    370     /***
    371      * Compute the
    372      * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
    373      * hyperbolic sine</a> for the given complex argument.
    374      * <p>
    375      * Implements the formula: <pre>
    376      * <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
    377      * where the (real) functions on the right-hand side are
    378      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    379      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
    380      * <p>
    381      * Returns {@link Complex#NaN} if either real or imaginary part of the
    382      * input argument is <code>NaN</code>.
    383      * <p>
    384      * Infinite values in real or imaginary parts of the input may result in
    385      * infinite or NaN values returned in parts of the result.<pre>
    386      * Examples:
    387      * <code>
    388      * sinh(1 &plusmn; INFINITY i) = NaN + NaN i
    389      * sinh(&plusmn;INFINITY + i) = &plusmn; INFINITY + INFINITY i
    390      * sinh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre
    391      *
    392      * @param z the value whose hyperbolic sine is to be returned
    393      * @return the hyperbolic sine of <code>z</code>
    394      * @throws NullPointerException if <code>z</code> is null
    395      */
    396     public static Complex sinh(Complex z) {
    397         if (z.isNaN()) {
    398             return Complex.NaN;
    399         }
    400
    401         double a = z.getReal();
    402         double b = z.getImaginary();
    403
    404         return new Complex(MathUtils.sinh(a) * Math.cos(b),
    405             MathUtils.cosh(a) * Math.sin(b));
    406     }
    407
    408     /***
    409      * Compute the
    410      * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
    411      * square root</a> for the given complex argument.
    412      * <p>
    413      * Implements the following algorithm to compute <code>sqrt(a + bi)</code>:
    414      * <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
    415      * <li><pre>if <code> a &#8805; 0</code> return <code>t + (b/2t)i</code>
    416      *  else return <code>|b|/2t + sign(b)t i </code></pre></li>
    417      * </ol>
    418      * where <ul>
    419      * <li><code>|a| = {@link Math#abs}(a)</code></li>
    420      * <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
    421      * <li><code>sign(b) =  {@link MathUtils#indicator}(b) </code>
    422      * </ul>
    423      * <p>
    424      * Returns {@link Complex#NaN} if either real or imaginary part of the
    425      * input argument is <code>NaN</code>.
    426      * <p>
    427      * Infinite values in real or imaginary parts of the input may result in
    428      * infinite or NaN values returned in parts of the result.<pre>
    429      * Examples:
    430      * <code>
    431      * sqrt(1 &plusmn; INFINITY i) = INFINITY + NaN i
    432      * sqrt(INFINITY + i) = INFINITY + 0i
    433      * sqrt(-INFINITY + i) = 0 + INFINITY i
    434      * sqrt(INFINITY &plusmn; INFINITY i) = INFINITY + NaN i
    435      * sqrt(-INFINITY &plusmn; INFINITY i) = NaN &plusmn; INFINITY i
    436      * </code></pre>
    437      *
    438      * @param z the value whose square root is to be returned
    439      * @return the square root of <code>z</code>
    440      * @throws NullPointerException if <code>z</code> is null
    441      */
    442     public static Complex sqrt(Complex z) {
    443         if (z.isNaN()) {
    444             return Complex.NaN;
    445         }
    446
    447         double a = z.getReal();
    448         double b = z.getImaginary();
    449
    450         double t = Math.sqrt((Math.abs(a) + z.abs()) / 2.0);
    451         if (a >= 0.0) {
    452             return new Complex(t, b / (2.0 * t));
    453         } else {
    454             return new Complex(Math.abs(b) / (2.0 * t),
    455                 MathUtils.indicator(b) * t);
    456         }
    457     }
    458
    459     /***
    460      * Compute the
    461      * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
    462      * square root</a> of 1 - <code>z</code><sup>2</sup> for the given complex
    463      * argument.
    464      * <p>
    465      * Computes the result directly as
    466      * <code>sqrt(Complex.ONE.subtract(z.multiply(z)))</code>.
    467      * <p>
    468      * Returns {@link Complex#NaN} if either real or imaginary part of the
    469      * input argument is <code>NaN</code>.
    470      * <p>
    471      * Infinite values in real or imaginary parts of the input may result in
    472      * infinite or NaN values returned in parts of the result.
    473      *
    474      * @param z the value
    475      * @return the square root of 1 - <code>z</code><sup>2</sup>
    476      * @throws NullPointerException if <code>z</code> is null
    477      */
    478     public static Complex sqrt1z(Complex z) {
    479         return sqrt(Complex.ONE.subtract(z.multiply(z)));
    480     }
    481
    482     /***
    483      * Compute the
    484      * <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
    485      * tangent</a> for the given complex argument.
    486      * <p>
    487      * Implements the formula: <pre>
    488      * <code>tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i</code></pre>
    489      * where the (real) functions on the right-hand side are
    490      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    491      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
    492      * <p>
    493      * Returns {@link Complex#NaN} if either real or imaginary part of the
    494      * input argument is <code>NaN</code>.
    495      * <p>
    496      * Infinite (or critical) values in real or imaginary parts of the input may
    497      * result in infinite or NaN values returned in parts of the result.<pre>
    498      * Examples:
    499      * <code>
    500      * tan(1 &plusmn; INFINITY i) = 0 + NaN i
    501      * tan(&plusmn;INFINITY + i) = NaN + NaN i
    502      * tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
    503      * tan(&plusmn;&pi/2 + 0 i) = &plusmn;INFINITY + NaN i</code></pre>
    504      *
    505      * @param z the value whose tangent is to be returned
    506      * @return the tangent of <code>z</code>
    507      * @throws NullPointerException if <code>z</code> is null
    508      */
    509     public static Complex tan(Complex z) {
    510         if (z.isNaN()) {
    511             return Complex.NaN;
    512         }
    513
    514         double a2 = 2.0 * z.getReal();
    515         double b2 = 2.0 * z.getImaginary();
    516         double d = Math.cos(a2) + MathUtils.cosh(b2);
    517
    518         return new Complex(Math.sin(a2) / d, MathUtils.sinh(b2) / d);
    519     }
    520
    521     /***
    522      * Compute the
    523      * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
    524      * hyperbolic tangent</a> for the given complex argument.
    525     * <p>
    526      * Implements the formula: <pre>
    527      * <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i</code></pre>
    528      * where the (real) functions on the right-hand side are
    529      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    530      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.
    531      * <p>
    532      * Returns {@link Complex#NaN} if either real or imaginary part of the
    533      * input argument is <code>NaN</code>.
    534      * <p>
    535      * Infinite values in real or imaginary parts of the input may result in
    536      * infinite or NaN values returned in parts of the result.<pre>
    537      * Examples:
    538      * <code>
    539      * tanh(1 &plusmn; INFINITY i) = NaN + NaN i
    540      * tanh(&plusmn;INFINITY + i) = NaN + 0 i
    541      * tanh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
    542      * tanh(0 + (&pi/2)i) = NaN + INFINITY i</code></pre>
    543      *
    544      * @param z the value whose hyperbolic tangent is to be returned
    545      * @return the hyperbolic tangent of <code>z</code>
    546      * @throws NullPointerException if <code>z</code> is null
    547      */
    548     public static Complex tanh(Complex z) {
    549         if (z.isNaN()) {
    550             return Complex.NaN;
    551         }
    552
    553         double a2 = 2.0 * z.getReal();
    554         double b2 = 2.0 * z.getImaginary();
    555         double d = MathUtils.cosh(a2) + Math.cos(b2);
    556
    557         return new Complex(MathUtils.sinh(a2) / d, Math.sin(b2) / d);
    558     }
    559 }