/* * Copyright 2003-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This code is modified for the MathEclipse project */ package org.matheclipse.core.expression; import org.matheclipse.parser.client.math.MathUtils; /** * Static implementations of common * {@link org.matheclipse.parser.client.math.Complex}-valued functions. Included * are trigonometric, exponential, log, power and square root functions. ** @throws NullPointerException if* Reference: *
* See individual method javadocs for the computational formulas used. * In general, NaN values in either real or imaginary parts of input arguments * result in {@link ComplexNum#NaN} returned. Otherwise, infinite or NaN values * are returned as they arise in computing the real functions specified in the * computational formulas. Null arguments result in NullPointerExceptions. * * @version $Revision: 1.7 $ $Date: 2008/09/07 10:01:54 $ */ public class ComplexUtils { /** * Default constructor. */ private ComplexUtils() { super(); } /** * Compute the * * inverse cosine for the given complex argument. ** Implements the formula:
**acos(z) = -i (log(z + i (sqrt(1 - z2))))* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaNor infinite. * * @param z the value whose inverse cosine is to be returned * @return the inverse cosine ofz* @throws NullPointerException ifzis null */ public static ComplexNum acos(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } return ComplexNum.I.negate().multiply(log(z.add( ComplexNum.I.multiply(sqrt1z(z))))); } /** * Compute the * * inverse sine for the given complex argument. ** Implements the formula:
**asin(z) = -i (log(sqrt(1 - z2) + iz))* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaNor infinite. * * @param z the value whose inverse sine is to be returned. * @return the inverse sine ofz. * @throws NullPointerException ifzis null */ public static ComplexNum asin(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } return ComplexNum.I.negate().multiply(log(sqrt1z(z).add( ComplexNum.I.multiply(z)))); } /** * Compute the * * inverse tangent for the given complex argument. ** Implements the formula:
**atan(z) = (i/2) log((i + z)/(i - z))* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaNor infinite. * * @param z the value whose inverse tangent is to be returned * @return the inverse tangent ofz* @throws NullPointerException ifzis null */ public static ComplexNum atan(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } return ComplexNum.I.multiply( log(ComplexNum.I.add(z).divide(ComplexNum.I.subtract(z)))) .divide(ComplexNum.valueOf(2.0, 0.0)); } /** * Compute the * * cosine * for the given complex argument. ** Implements the formula:
** where the (real) functions on the right-hand side are * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, * {@link MathUtils#cosh} and {@link MathUtils#sinh}. *cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaN. ** Infinite values in real or imaginary parts of the input may result in * infinite or NaN values returned in parts of the result.
* Examples: ** * @param z the value whose cosine is to be returned * @return the cosine of* cos(1 ± INFINITY i) = 1 ∓ INFINITY i * cos(±INFINITY + i) = NaN + NaN i * cos(±INFINITY ± INFINITY i) = NaN + NaN iz* @throws NullPointerException ifzis null */ public static ComplexNum cos(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } final double a = z.getReal(); final double b = z.getImaginary(); return ComplexNum.valueOf(Math.cos(a) * MathUtils.cosh(b), -Math.sin(a) * MathUtils.sinh(b)); } /** * Compute the * * hyperbolic cosine for the given complex argument. ** Implements the formula:
** where the (real) functions on the right-hand side are * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, * {@link MathUtils#cosh} and {@link MathUtils#sinh}. *cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaN. ** Infinite values in real or imaginary parts of the input may result in * infinite or NaN values returned in parts of the result.
* Examples: *** cosh(1 ± INFINITY i) = NaN + NaN i * cosh(±INFINITY + i) = INFINITY ± INFINITY i * cosh(±INFINITY ± INFINITY i) = NaN + NaN i* Throws
NullPointerExceptionif z is null. * * @param z the value whose hyperbolic cosine is to be returned. * @return the hyperbolic cosine ofz. */ public static ComplexNum cosh(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } final double a = z.getReal(); final double b = z.getImaginary(); return ComplexNum.valueOf(MathUtils.cosh(a) * Math.cos(b), MathUtils.sinh(a) * Math.sin(b)); } /** * Compute the * * exponential function for the given complex argument. ** Implements the formula:
** where the (real) functions on the right-hand side are * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and * {@link java.lang.Math#sin}. *exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaN. ** Infinite values in real or imaginary parts of the input may result in * infinite or NaN values returned in parts of the result.
* Examples: *** exp(1 ± INFINITY i) = NaN + NaN i * exp(INFINITY + i) = INFINITY + INFINITY i * exp(-INFINITY + i) = 0 + 0i * exp(±INFINITY ± INFINITY i) = NaN + NaN i* Throws
NullPointerExceptionif z is null. * * @param z the value * @return ez*/ public static ComplexNum exp(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } final double b = z.getImaginary(); final double expA = Math.exp(z.getReal()); return ComplexNum.valueOf(expA * Math.cos(b), expA * Math.sin(b)); } /** * Compute the * * natural logarithm for the given complex argument. ** Implements the formula:
** where ln on the right hand side is {@link java.lang.Math#log}, *log(a + bi) = ln(|a + bi|) + arg(a + bi)i|a + bi|is the modulus, {@link ComplexNum#abs}, and *arg(a + bi) = {@link java.lang.Math#atan2}(b, a)** Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaN. ** Infinite (or critical) values in real or imaginary parts of the input may * result in infinite or NaN values returned in parts of the result.
* Examples: ** Throws* log(1 ± INFINITY i) = INFINITY ± (π/2)i * log(INFINITY + i) = INFINITY + 0i * log(-INFINITY + i) = INFINITY + πi * log(INFINITY ± INFINITY i) = INFINITY ± (π/4)i * log(-INFINITY ± INFINITY i) = INFINITY ± (3π/4)i * log(0 + 0i) = -INFINITY + 0i *NullPointerExceptionif z is null. * * @param z the value. * @return lnz. */ public static ComplexNum log(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } return ComplexNum.valueOf(Math.log(z.dabs()), Math.atan2(z.getImaginary(), z.getReal())); } /** * Creates a complex number from the given polar representation. ** The value returned is
r·ei·theta, * computed asr·cos(theta) + r·sin(theta)i** If either
rorthetais NaN, or *thetais infinite, {@link ComplexNum#NaN} is returned. ** If
ris infinite andthetais finite, * infinite or NaN values may be returned in parts of the result, following * the rules for double arithmetic.* Examples: ** * @param r the modulus of the complex number to create * @param theta the argument of the complex number to create * @return* polar2Complex(INFINITY, π/4) = INFINITY + INFINITY i * polar2Complex(INFINITY, 0) = INFINITY + NaN i * polar2Complex(INFINITY, -π/4) = INFINITY - INFINITY i * polar2Complex(INFINITY, 5π/4) = -INFINITY - INFINITY ir·ei·theta* @throws IllegalArgumentException if r is negative * @since 1.1 */ public static ComplexNum polar2Complex(final double r, final double theta) { if (r < 0) { throw new IllegalArgumentException ("DoubleComplexImpl modulus must not be negative"); } return ComplexNum.valueOf(r * Math.cos(theta), r * Math.sin(theta)); } /** * Returns of value ofyraised to the power ofx. ** Implements the formula:
** whereyx = exp(x·log(y))expandlogare {@link #exp} and * {@link #log}, respectively. ** Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaNor infinite, or ify* equals {@link ComplexNum#ZERO}. * * @param y the base. * @param x the exponent. * @returnyx* @throws NullPointerException if either x or y is null */ public static ComplexNum pow(final ComplexNum y, final ComplexNum x) { return exp(x.multiply(log(y))); } /** * Compute the * * sine * for the given complex argument. ** Implements the formula:
** where the (real) functions on the right-hand side are * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, * {@link MathUtils#cosh} and {@link MathUtils#sinh}. *sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaN. ** Infinite values in real or imaginary parts of the input may result in * infinite or NaN values returned in parts of the result.
* Examples: ** * Throws* sin(1 ± INFINITY i) = 1 ± INFINITY i * sin(±INFINITY + i) = NaN + NaN i * sin(±INFINITY ± INFINITY i) = NaN + NaN iNullPointerExceptionif z is null. * * @param z the value whose sine is to be returned. * @return the sine ofz. */ public static ComplexNum sin(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } final double a = z.getReal(); final double b = z.getImaginary(); return ComplexNum.valueOf(Math.sin(a) * MathUtils.cosh(b), Math.cos(a) * MathUtils.sinh(b)); } /** * Compute the * * hyperbolic sine for the given complex argument. ** Implements the formula:
** where the (real) functions on the right-hand side are * {@link java.lang.Math#sin}, {@link java.lang.Math#cos}, * {@link MathUtils#cosh} and {@link MathUtils#sinh}. *sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i* Returns {@link ComplexNum#NaN} if either real or imaginary part of the * input argument is
NaN. ** Infinite values in real or imaginary parts of the input may result in * infinite or NaN values returned in parts of the result.
* Examples: *z* sinh(1 ± INFINITY i) = NaN + NaN i * sinh(±INFINITY + i) = ± INFINITY + INFINITY i * sinh(±INFINITY ± INFINITY i) = NaN + NaN izis null */ public static ComplexNum sinh(final ComplexNum z) { if (z.isNaN()) { return ComplexNum.NaN; } final double a = z.getReal(); final double b = z.getImaginary(); return ComplexNum.valueOf(MathUtils.sinh(a) * Math.cos(b), MathUtils.cosh(a) * Math.sin(b)); } /** * Compute the * * square root for the given complex argument. ** Implements the following algorithm to compute
sqrt(a + bi): ** where
- Let
*t = sqrt((|a| + |a + bi|) / 2)- *
ifa ≥ 0returnt + (b/2t)i* else return|b|/2t + sign(b)t i
|a| = {@link Math#abs}(a)|a + bi| = {@link ComplexNum#abs}(a + bi) sign(b) = {@link MathUtils#indicator}(b)
*
* Returns {@link ComplexNum#NaN} if either real or imaginary part of the
* input argument is NaN.
*
* Infinite values in real or imaginary parts of the input may result in * infinite or NaN values returned in parts of the result.
* Examples:
*
* sqrt(1 ± INFINITY i) = INFINITY + NaN i
* sqrt(INFINITY + i) = INFINITY + 0i
* sqrt(-INFINITY + i) = 0 + INFINITY i
* sqrt(INFINITY ± INFINITY i) = INFINITY + NaN i
* sqrt(-INFINITY ± INFINITY i) = NaN ± INFINITY i
*
*
* @param z the value whose square root is to be returned
* @return the square root of z
* @throws NullPointerException if z is null
*/
public static ComplexNum sqrt(final ComplexNum z) {
if (z.isNaN()) {
return ComplexNum.NaN;
}
final double a = z.getReal();
final double b = z.getImaginary();
final double t = Math.sqrt((Math.abs(a) + z.dabs()) / 2.0);
if (a >= 0.0) {
return ComplexNum.valueOf(t, b / (2.0 * t));
} else {
return ComplexNum.valueOf(Math.abs(b) / (2.0 * t),
MathUtils.indicator(b) * t);
}
}
/**
* Compute the
*
* square root of 1 - z2 for the given complex
* argument.
*
* Computes the result directly as
* sqrt(DoubleComplexImpl.ONE.subtract(z.multiply(z))).
*
* Returns {@link ComplexNum#NaN} if either real or imaginary part of the
* input argument is NaN.
*
* Infinite values in real or imaginary parts of the input may result in
* infinite or NaN values returned in parts of the result.
*
* @param z the value
* @return the square root of 1 - z2
* @throws NullPointerException if z is null
*/
public static ComplexNum sqrt1z(final ComplexNum z) {
return sqrt(ComplexNum.ONE.subtract(z.multiply(z)));
}
/**
* Compute the
*
* tangent for the given complex argument.
*
* Implements the formula:
* tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i
* where the (real) functions on the right-hand side are
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
*
* Returns {@link ComplexNum#NaN} if either real or imaginary part of the
* input argument is NaN.
*
* Infinite (or critical) values in real or imaginary parts of the input may * result in infinite or NaN values returned in parts of the result.
* Examples:
*
* tan(1 ± INFINITY i) = 0 + NaN i
* tan(±INFINITY + i) = NaN + NaN i
* tan(±INFINITY ± INFINITY i) = NaN + NaN i
* tan(±&pi/2 + 0 i) = ±INFINITY + NaN i
*
* @param z the value whose tangent is to be returned
* @return the tangent of z
* @throws NullPointerException if z is null
*/
public static ComplexNum tan(final ComplexNum z) {
if (z.isNaN()) {
return ComplexNum.NaN;
}
final double a2 = 2.0 * z.getReal();
final double b2 = 2.0 * z.getImaginary();
final double d = Math.cos(a2) + MathUtils.cosh(b2);
return ComplexNum.valueOf(Math.sin(a2) / d, MathUtils.sinh(b2) / d);
}
/**
* Compute the
*
* hyperbolic tangent for the given complex argument.
* * Implements the formula:
* tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i
* where the (real) functions on the right-hand side are
* {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
* {@link MathUtils#cosh} and {@link MathUtils#sinh}.
*
* Returns {@link ComplexNum#NaN} if either real or imaginary part of the
* input argument is NaN.
*
* Infinite values in real or imaginary parts of the input may result in * infinite or NaN values returned in parts of the result.
* Examples:
*
* tanh(1 ± INFINITY i) = NaN + NaN i
* tanh(±INFINITY + i) = NaN + 0 i
* tanh(±INFINITY ± INFINITY i) = NaN + NaN i
* tanh(0 + (&pi/2)i) = NaN + INFINITY i
*
* @param z the value whose hyperbolic tangent is to be returned
* @return the hyperbolic tangent of z
* @throws NullPointerException if z is null
*/
public static ComplexNum tanh(final ComplexNum z) {
if (z.isNaN()) {
return ComplexNum.NaN;
}
final double a2 = 2.0 * z.getReal();
final double b2 = 2.0 * z.getImaginary();
final double d = MathUtils.cosh(a2) + Math.cos(b2);
return ComplexNum.valueOf(MathUtils.sinh(a2) / d, Math.sin(b2) / d);
}
}
Ads help maintain this website.