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 }