1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 }