/*
 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
 * Copyright (C) 2006 - JScience (http://jscience.org/)
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and distribute this software is
 * freely granted, provided that this notice is preserved.
 */
package org.jscience.mathematics.number;

import java.io.IOException;

import org.jscience.mathematics.structure.Field;

import javolution.lang.MathLib;
import javolution.text.Text;
import javolution.text.TextFormat;
import javolution.text.TypeFormat;
import javolution.context.ObjectFactory;
import javolution.xml.XMLFormat;
import javolution.xml.stream.XMLStreamException;

//@RETROWEAVER import javolution.text.Appendable;

/**
 * 

This class represents an immutable complex number.

* * @author Jean-Marie Dautelle * @version 3.0, February 13, 2006 * @see * Wikipedia: Complex number */ public final class Complex extends Number implements Field { /** * Holds the local text format for complex numbers (cartesian form * by default, e.g. "2.34 - 0.4i"). */ private static final TextFormat CARTESIAN_FORMAT = new TextFormat() { public Appendable format(Complex complex, Appendable appendable) throws IOException { TypeFormat.format(complex._real, appendable); if (complex._imaginary < 0.0) { appendable.append(" - "); TypeFormat.format(-complex._imaginary, appendable); } else { appendable.append(" + "); TypeFormat.format(complex._imaginary, appendable); } return appendable.append('i'); } public Complex parse(CharSequence csq, Cursor cursor) { // Reads real part. double real = TypeFormat.parseDouble(csq, cursor); // Reads separator. cursor.skip(' ', csq); char op = cursor.next(csq); if ((op != '+') && (op != '-')) throw new NumberFormatException("'+' or '-' expected"); cursor.skip(' ', csq); // Reads imaginary part. double imaginary = TypeFormat.parseDouble(csq, cursor); char i = cursor.next(csq); if (i != 'i') throw new NumberFormatException("'i' expected"); return Complex.valueOf(real, op == '-' ? -imaginary : imaginary); } }; static { // Sets default format to cartesian, users can always change it to polar. TextFormat.setInstance(Complex.class, CARTESIAN_FORMAT); } /** * The complex number zero. */ public static final Complex ZERO = new Complex(0.0, 0.0); /** * The complex number one. */ public static final Complex ONE = new Complex(1.0, 0.0); /** * The imaginary unit i. */ public static final Complex I = new Complex(0.0, 1.0); /** * Holds the default XML representation for complex numbers. * This representation consists of real and * imaginary attributes (e.g. * <Complex real="2.34" imaginary="-0.4"/>). */ static final XMLFormat XML = new XMLFormat(Complex.class) { @Override public Complex newInstance(Class cls, InputElement xml) throws XMLStreamException { return Complex.valueOf(xml.getAttribute("real", 0.0), xml .getAttribute("imaginary", 0.0)); } public void write(Complex complex, OutputElement xml) throws XMLStreamException { xml.setAttribute("real", complex._real); xml.setAttribute("imaginary", complex._imaginary); } public void read(InputElement xml, Complex complex) { // Nothing to do, immutable. } }; /** * Holds the factory constructing complex instances. */ private static final ObjectFactory FACTORY = new ObjectFactory() { protected Complex create() { return new Complex(); } }; /** * Holds the real component. */ private double _real; /** * Holds the imaginary component. */ private double _imaginary; /** * Default constructor. */ private Complex() { } /** * Creates a complex number having the specified real and imaginary * components. * * @param real the real component of this complex number. * @param imaginary the imaginary component of this complex number. */ private Complex(double real, double imaginary) { _real = real; _imaginary = imaginary; } /** * Returns the complex number having the specified real and imaginary * components. * * @param real the real component of this complex number. * @param imaginary the imaginary component of this complex number. * @return the corresponding complex number. * @see #getReal * @see #getImaginary */ public static Complex valueOf(double real, double imaginary) { Complex c = FACTORY.object(); c._real = real; c._imaginary = imaginary; return c; } /** * Returns the complex number for the specified character sequence. * * @param csq the character sequence. * @return TextFormat.getInstance(Complex.class).parse(csq) * @throws IllegalArgumentException if the character sequence does not * contain a parsable complex number. * @see TextFormat#getInstance(Class) */ public static Complex valueOf(CharSequence csq) { return TextFormat.getInstance(Complex.class).parse(csq); } /** * Indicates if either the real or imaginary component of this complex * is infinite. * * @return true if this complex is infinite; * false otherwise. */ public boolean isInfinite() { return Double.isInfinite(_real) | Double.isInfinite(_imaginary); } /** * Indicates if either the real or imaginary component of this complex * is not a number. * * @return true if this complex is NaN; * false otherwise. */ public boolean isNaN() { return Double.isNaN(_real) | Double.isNaN(_imaginary); } /** * Returns the real component of this complex number. * * @return the real component. */ public double getReal() { return _real; } /** * Returns the imaginary component of this complex number. * * @return the imaginary component. */ public double getImaginary() { return _imaginary; } /** * Returns the negation of this complex. * * @return -this. */ public Complex opposite() { Complex c = FACTORY.object(); c._real = -this._real; c._imaginary = -this._imaginary; return c; } /** * Returns the sum of this complex with the one specified. * * @param that the complex to be added. * @return this + that. */ public Complex plus(Complex that) { Complex c = FACTORY.object(); c._real = this._real + that._real; c._imaginary = this._imaginary + that._imaginary; return c; } /** * Returns the difference between this complex and the one specified. * * @param that the complex to be subtracted. * @return this - that. */ public Complex minus(Complex that) { Complex c = FACTORY.object(); c._real = this._real - that._real; c._imaginary = this._imaginary - that._imaginary; return c; } /** * Returns this complex multiplied by the specified factor. * * @param k the factor multiplier. * @return this * k. */ public Complex times(double k) { Complex c = FACTORY.object(); c._real = this._real * k; c._imaginary = this._imaginary * k; return c; } /** * Returns the product of this complex with the one specified. * * @param that the complex multiplier. * @return this * that. */ public Complex times(Complex that) { Complex c = FACTORY.object(); c._real = this._real * that._real - this._imaginary * that._imaginary; c._imaginary = this._real * that._imaginary + this._imaginary * that._real; return c; } /** * Returns the inverse of this complex. * * @return 1 / this. */ public Complex inverse() { Complex c = FACTORY.object(); double tmp = (this._real * this._real) + (this._imaginary * this._imaginary); c._real = this._real / tmp; c._imaginary = -this._imaginary / tmp; return c; } /** * Returns this complex divided by the specified factor. * * @param k the factor divisor. * @return this / k. */ public Complex divide(double k) { Complex c = FACTORY.object(); c._real = this._real / k; c._imaginary = this._imaginary / k; return c; } /** * Returns this complex divided by the specified complex. * * @param that the complex divisor. * @return this / that. */ public Complex divide(Complex that) { double tmp = (that._real * that._real) + (that._imaginary * that._imaginary); double thatInvReal = that._real / tmp; double thatInvImaginary = -that._imaginary / tmp; Complex c = FACTORY.object(); c._real = this._real * thatInvReal - this._imaginary * thatInvImaginary; c._imaginary = this._real * thatInvImaginary + this._imaginary * thatInvReal; return c; } /** * Returns the conjugate of this complex number. * * @return (this.real(), - this.imaginary()). */ public Complex conjugate() { Complex c = FACTORY.object(); c._real = this._real; c._imaginary = -this._imaginary; return c; } /** * Returns the magnitude of this complex number, also referred to * as the "modulus" or "length". * * @return the magnitude of this complex number. */ public double magnitude() { return MathLib.sqrt(_real * _real + _imaginary * _imaginary); } /** * Returns the argument of this complex number. It is the angle * in radians, measured counter-clockwise from the real axis. * * @return argument of this complex number. */ public double argument() { return MathLib.atan2(_imaginary, _real); } /** * Returns one of the two square root of this complex number. * * @return sqrt(this). */ public Complex sqrt() { Complex c = FACTORY.object(); double m = MathLib.sqrt(this.magnitude()); double a = this.argument() / 2.0; c._real = m * MathLib.cos(a); c._imaginary = m * MathLib.sin(a); return c; } /** * Returns the exponential number e raised to the power of * this complex. * Note: ePI*i * = -1 * * @return exp(this). */ public Complex exp() { Complex c = FACTORY.object(); double m = MathLib.exp(this._real); c._real = m * MathLib.cos(this._imaginary); c._imaginary = m * MathLib.sin(this._imaginary); return c; } /** * Returns the principal natural logarithm (base e) of this complex. * Note: There are an infinity of solutions. * * @return log(this). */ public Complex log() { Complex c = FACTORY.object(); c._real = MathLib.log(this.magnitude()); c._imaginary = this.argument(); return c; } /** * Returns this complex raised to the specified power. * * @param e the exponent. * @return this**e. */ public Complex pow(double e) { Complex c = FACTORY.object(); double m = MathLib.pow(this.magnitude(), e); double a = this.argument() * e; c._real = m * MathLib.cos(a); c._imaginary = m * MathLib.sin(a); return c; } /** * Returns this complex raised to the power of the specified complex * exponent. * * @param that the exponent. * @return this**that. */ public Complex pow(Complex that) { Complex c = FACTORY.object(); double r1 = MathLib.log(this.magnitude()); double i1 = this.argument(); double r2 = (r1 * that._real) - (i1 * that._imaginary); double i2 = (r1 * that._imaginary) + (i1 * that._real); double m = MathLib.exp(r2); c._real = m * MathLib.cos(i2); c._imaginary = m * MathLib.sin(i2); return c; } /** * Indicates if two complexes are "sufficiently" alike to be considered * equal. * * @param that the complex to compare with. * @param tolerance the maximum magnitude of the difference between * them before they are considered not equal. * @return true if they are considered equal; * false otherwise. */ public boolean equals(Complex that, double tolerance) { return MathLib.abs(this.minus(that).magnitude()) <= tolerance; } /** * Compares this complex against the specified Object. * * @param that the object to compare with. * @return true if the objects are the same; * false otherwise. */ public boolean equals(Object that) { return (that instanceof Complex) && (this._real == ((Complex) that)._real) && (this._imaginary == ((Complex) that)._imaginary); } /** * Returns the hash code for this complex number. * * @return the hash code value. */ public int hashCode() { int h = Float.floatToIntBits((float) _real) ^ Float.floatToIntBits((float) (_imaginary * MathLib.PI)); h += ~(h << 9); h ^= (h >>> 14); h += (h << 4); return h ^ (h >>> 10); } /** * Returns the text representation of this complex number. * * @return TextFormat.getInstance(Complex.class).format(this) * @see TextFormat#getInstance(Class) */ public Text toText() { return TextFormat.getInstance(Complex.class).format(this); } /** * Returns the {@link #getReal real} component of this {@link Complex} * number as a long. * * @return (long) this.getReal() */ public long longValue() { return (long) _real; } /** * Returns the {@link #getReal real} component of this {@link Complex} * number as a double. * * @return (double) this.getReal() */ public double doubleValue() { return _real; } /** * Compares two complex numbers, the real components are compared first, * then if equal, the imaginary components. * * @param that the complex number to be compared with. * @return -1, 0, 1 based upon the ordering. */ public int compareTo(Complex that) { if (this._real < that._real) return -1; if (this._real > that._real) return 1; long l1 = Double.doubleToLongBits(this._real); long l2 = Double.doubleToLongBits(that._real); if (l1 < l2) return -1; if (l2 > l1) return 1; if (this._imaginary < that._imaginary) return -1; if (this._imaginary > that._imaginary) return 1; l1 = Double.doubleToLongBits(this._imaginary); l2 = Double.doubleToLongBits(that._imaginary); if (l1 < l2) return -1; if (l2 > l1) return 1; return 0; } /** * Compares the {@link #magnitude() magnitude} of this complex number * with the magnitude of the complex number specified. * * @param that the complex number to be compared with. * @return |this| > |that| */ public boolean isLargerThan(Complex that) { return this.magnitude() > that.magnitude(); } @Override public Complex copy() { return Complex.valueOf(_real, _imaginary); } private static final long serialVersionUID = 1L; }

Ads help maintain this website.