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