View Javadoc

    1   /*
    2    * Copyright 2003-2004 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   * Implementations of various transcendental functions for
    23   * {@link org.apache.commons.math.complex.Complex} arguments.
    24   *
    25   * Reference:
    26   * <ul>
    27   * <li><a href="http://myweb.lmu.edu/dmsmith/ZMLIB.pdf">
    28   * Multiple Precision Complex Arithmetic and Functions</a></li>
    29   * </ul>
    30   *
    31   * @version $Revision: 1.1 $ $Date: 2004/07/12 00:27:09 $
    32   */
    33  public class ComplexUtils {
    34
    35      /***
    36       * Default constructor.
    37       */
    38      private ComplexUtils() {
    39          super();
    40      }
    41
    42      /***
    43       * Compute the <a href="http://mathworld.wolfram.com/InverseCosine.html">
    44       * inverse cosine</a> for the given complex argument.
    45       * @param z the value whose inverse cosine is to be returned.
    46       * @return the inverse cosine of <code>z</code>.
    47       */
    48      public static Complex acos(Complex z) {
    49          if (z.isNaN()) {
    50              return Complex.NaN;
    51          }
    52
    53          return Complex.I.negate().multiply(log(z.add(
    54              Complex.I.multiply(sqrt1z(z)))));
    55      }
    56
    57      /***
    58       * Compute the <a href="http://mathworld.wolfram.com/InverseSine.html">
    59       * inverse sine</a> for the given complex argument.
    60       * @param z the value whose inverse sine is to be returned.
    61       * @return the inverse sine of <code>z</code>.
    62       */
    63      public static Complex asin(Complex z) {
    64          if (z.isNaN()) {
    65              return Complex.NaN;
    66          }
    67
    68          return Complex.I.negate().multiply(log(sqrt1z(z).add(
    69              Complex.I.multiply(z))));
    70      }
    71
    72      /***
    73       * Compute the <a href="http://mathworld.wolfram.com/InverseTangent.html">
    74       * inverse tangent</a> for the given complex argument.
    75       * @param z the value whose inverse tangent is to be returned.
    76       * @return the inverse tangent of <code>z</code>.
    77       */
    78      public static Complex atan(Complex z) {
    79          if (z.isNaN()) {
    80              return Complex.NaN;
    81          }
    82
    83
    84          return Complex.I.multiply(
    85              log(Complex.I.add(z).divide(Complex.I.subtract(z))))
    86              .divide(new Complex(2.0, 0.0));
    87      }
    88
    89      /***
    90       * Compute the <a href="http://mathworld.wolfram.com/Cosine.html">cosine</a>
    91       * for the given complex argument.
    92       * @param z the value whose cosine is to be returned.
    93       * @return the cosine of <code>z</code>.
    94       */
    95      public static Complex cos(Complex z) {
    96          if (z.isNaN()) {
    97              return Complex.NaN;
    98          }
    99
    100         double a = z.getReal();
    101         double b = z.getImaginary();
    102
    103         return new Complex(Math.cos(a) * MathUtils.cosh(b),
    104             -Math.sin(a) * MathUtils.sinh(b));
    105     }
    106
    107     /***
    108      * Compute the <a href="http://mathworld.wolfram.com/HyperbolicCosine.html">
    109      * hyperbolic cosine</a> for the given complex argument.
    110      * @param z the value whose hyperbolic cosine is to be returned.
    111      * @return the hyperbolic cosine of <code>z</code>.
    112      */
    113     public static Complex cosh(Complex z) {
    114         if (z.isNaN()) {
    115             return Complex.NaN;
    116         }
    117
    118         double a = z.getReal();
    119         double b = z.getImaginary();
    120
    121         return new Complex(MathUtils.cosh(a) * Math.cos(b),
    122             MathUtils.sinh(a) * Math.sin(b));
    123     }
    124
    125     /***
    126      * Compute the
    127      * <a href="http://mathworld.wolfram.com/ExponentialFunction.html">
    128      * exponential function</a> for the given complex argument.
    129      * @param z the value.
    130      * @return <i>e</i><sup><code>z</code></sup>.
    131      */
    132     public static Complex exp(Complex z) {
    133         if (z.isNaN()) {
    134             return Complex.NaN;
    135         }
    136
    137         double b = z.getImaginary();
    138         double expA = Math.exp(z.getReal());
    139         double sinB = Math.sin(b);
    140         double cosB = Math.cos(b);
    141         return new Complex(expA * cosB, expA * sinB);
    142     }
    143
    144     /***
    145      * Compute the <a href="http://mathworld.wolfram.com/NaturalLogarithm.html">
    146      * natural logarithm</a> for the given complex argument.
    147      * @param z the value.
    148      * @return ln <code>z</code>.
    149      */
    150     public static Complex log(Complex z) {
    151         if (z.isNaN()) {
    152             return Complex.NaN;
    153         }
    154
    155         return new Complex(Math.log(z.abs()),
    156             Math.atan2(z.getImaginary(), z.getReal()));
    157     }
    158
    159
    160     /***
    161      * Returns of value of <code>y</code> raised to the power of <code>x</code>.
    162      * @param y the base.
    163      * @param x the exponent.
    164      * @return <code>y</code><sup><code>z</code></sup>.
    165      */
    166     public static Complex pow(Complex y, Complex x) {
    167         return exp(x.multiply(log(y)));
    168     }
    169
    170     /***
    171      * Compute the <a href="http://mathworld.wolfram.com/Sine.html">sine</a>
    172      * for the given complex argument.
    173      * @param z the value whose sine is to be returned.
    174      * @return the sine of <code>z</code>.
    175      */
    176     public static Complex sin(Complex z) {
    177         if (z.isNaN()) {
    178             return Complex.NaN;
    179         }
    180
    181         double a = z.getReal();
    182         double b = z.getImaginary();
    183
    184         return new Complex(Math.sin(a) * MathUtils.cosh(b),
    185             Math.cos(a) * MathUtils.sinh(b));
    186     }
    187
    188     /***
    189      * Compute the <a href="http://mathworld.wolfram.com/HyperbolicSine.html">
    190      * hyperbolic sine</a> for the given complex argument.
    191      * @param z the value whose hyperbolic sine is to be returned.
    192      * @return the hyperbolic sine of <code>z</code>.
    193      */
    194     public static Complex sinh(Complex z) {
    195         if (z.isNaN()) {
    196             return Complex.NaN;
    197         }
    198
    199         double a = z.getReal();
    200         double b = z.getImaginary();
    201
    202         return new Complex(MathUtils.sinh(a) * Math.cos(b),
    203             MathUtils.cosh(a) * Math.sin(b));
    204     }
    205
    206     /***
    207      * Compute the <a href="http://mathworld.wolfram.com/SquareRoot.html">squre
    208      * root</a> for the given complex argument.
    209      * @param z the value whose square root is to be returned.
    210      * @return the square root of <code>z</code>.
    211      */
    212     public static Complex sqrt(Complex z) {
    213         if (z.isNaN()) {
    214             return Complex.NaN;
    215         }
    216
    217         double a = z.getReal();
    218         double b = z.getImaginary();
    219
    220         double t = Math.sqrt((Math.abs(a) + z.abs()) / 2.0);
    221         if (a >= 0.0) {
    222             return new Complex(t, b / (2.0 * t));
    223         } else {
    224             return new Complex(Math.abs(z.getImaginary()) / (2.0 * t),
    225                 MathUtils.indicator(b) * t);
    226         }
    227     }
    228
    229     /***
    230      * Compute the <a href="http://mathworld.wolfram.com/SquareRoot.html">squre
    231      * root of 1 - <code>z</code><sup>2</sup> for the given complex argument.
    232      * @param z the value.
    233      * @return the square root of 1 - <code>z</code><sup>2</sup>.
    234      */
    235     public static Complex sqrt1z(Complex z) {
    236         return sqrt(Complex.ONE.subtract(z.multiply(z)));
    237     }
    238
    239     /***
    240      * Compute the <a href="http://mathworld.wolfram.com/Tangent.html">
    241      * tangent</a> for the given complex argument.
    242      * @param z the value whose tangent is to be returned.
    243      * @return the tangent of <code>z</code>.
    244      */
    245     public static Complex tan(Complex z) {
    246         if (z.isNaN()) {
    247             return Complex.NaN;
    248         }
    249
    250         double a2 = 2.0 * z.getReal();
    251         double b2 = 2.0 * z.getImaginary();
    252         double d = Math.cos(a2) + MathUtils.cosh(b2);
    253
    254         return new Complex(Math.sin(a2) / d, MathUtils.sinh(b2) / d);
    255     }
    256
    257     /***
    258      * Compute the
    259      * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html">
    260      * hyperbolic tangent</a> for the given complex argument.
    261      * @param z the value whose hyperbolic tangent is to be returned.
    262      * @return the hyperbolic tangent of <code>z</code>.
    263      */
    264     public static Complex tanh(Complex z) {
    265         if (z.isNaN()) {
    266             return Complex.NaN;
    267         }
    268
    269         double a2 = 2.0 * z.getReal();
    270         double b2 = 2.0 * z.getImaginary();
    271         double d = MathUtils.cosh(a2) + Math.cos(b2);
    272
    273         return new Complex(MathUtils.sinh(a2) / d, Math.sin(b2) / d);
    274     }
    275 }