/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2002-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.math; import java.io.Serializable; import org.geotoolkit.util.Cloneable; /** * A simple class for the handling of complex numbers. This is not the purpose of this class * to provides a full-fledged library for complex number handling. This class exists mostly * for the limited needs of some transformation methods. * <p> * For performance reasons, the methods in this class never create new objects. They always * operate on an object specified in argument, and store the result in the object on which * the method was invoked. * <p> * This class is final for performance reason. * * @author Justin Deoliveira (TOPP) * @author Martin Desruisseaux (IRD) * @version 3.00 * * @since 2.2 * @module */ public final class Complex implements Cloneable, Serializable { /** * For compatibility with previous versions during deserialization. */ private static final long serialVersionUID = -8143196508298758583L; /** * The real part of the complex number. */ public double real; /** * The imaginary part of the complex number. */ public double imag; /** * Creates a complex number initialized to (0,0). */ public Complex() { } /** * Creates a complex number initialized to the same value than the specified one. * * @param c The complex number to copy. */ public Complex(final Complex c) { real = c.real; imag = c.imag; } /** * Creates a complex number initialized to the specified real and imaginary parts. * * @param real The real part. * @param imag The imaginary part. */ public Complex(final double real, final double imag) { this.real = real; this.imag = imag; } /** * Set this complex number to the same value than the specified one. * This method computes the following: * * {@preformat java * this = c * } * * @param c The complex number to copy. */ public void copy(final Complex c) { real = c.real; imag = c.imag; } /** * Multiplies a complex number by a scalar. * This method computes the following: * * {@preformat java * this = c * s * } * * @param c The complex number to multiply with the scalar. * @param s The scalar value to multiply. */ public void multiply(final Complex c, final double s) { real = c.real * s; imag = c.imag * s; } /** * Multplies two complex numbers. * This method computes the following: * * {@preformat java * this = c1 * c2 * } * * @param c1 The first complex number to multiply. * @param c2 The second complex number to multiply. */ public void multiply(final Complex c1, final Complex c2) { final double x1 = c1.real; final double y1 = c1.imag; final double x2 = c2.real; final double y2 = c2.imag; real = (x1 * x2) - (y1 * y2); imag = (y1 * x2) + (x1 * y2); } /** * Divides one complex number by another. * This method computes the following: * * {@preformat java * this = c1 / c2 * } * * @param c1 The complex number. * @param c2 The complex divisor. */ public void divide(final Complex c1, final Complex c2) { final double x1 = c1.real; final double y1 = c1.imag; final double x2 = c2.real; final double y2 = c2.imag; final double denom = (x2 * x2) + (y2 * y2); real = ((x1 * x2) + (y1 * y2)) / denom; imag = ((y1 * x2) - (x1 * y2)) / denom; } /** * Adds to complex numbers. * This method computes the following: * * {@preformat java * this = c1 + c2 * } * * @param c1 The first complex number to add. * @param c2 The second complex number to add. */ public void add(final Complex c1, final Complex c2) { real = c1.real + c2.real; imag = c1.imag + c2.imag; } /** * Multplies two complex numbers, and add the result to a third one. * This method computes the following: * * {@preformat java * this = c0 + (c1 * c2) * } * * @param c1 The first complex number to multiply. * @param c2 The second complex number to multiply. * @param c0 The complex number to add to the product. */ public void addMultiply(final Complex c0, final Complex c1, final Complex c2) { final double x1 = c1.real; final double y1 = c1.imag; final double x2 = c2.real; final double y2 = c2.imag; real = c0.real + ((x1 * x2) - (y1 * y2)); imag = c0.imag + ((y1 * x2) + (x1 * y2)); } /** * Computes the integer power of a complex number up to 6. * This method computes the following: * * {@preformat java * this = c ^ power * } * * @param c The complex number to raise to a power. * @param power The power to raise the complex number. */ public void power(final Complex c, final int power) { final double x = c.real; final double y = c.imag; switch (power) { case 0: { real = 1; imag = 0; break; } case 1: { real = x; imag = y; break; } case 2: { real = (x * x) - (y * y); imag = 2 * x * y; break; } case 3: { final double x2 = x * x; final double y2 = y * y; real = x * (x2 - 3*y2); imag = y * (3*x2 - y2); break; } case 4: { final double x2 = x * x; final double y2 = y * y; real = (x2 * x2) - (6 * x2 * y2) + (y2 * y2); imag = 4 * (x * y) * (x2 - y2); break; } case 5: { final double x2 = x * x; final double y2 = y * y; final double x4 = x2 * x2; final double y4 = y2 * y2; final double cr = (x2* y2) * 10; real = x * (x4 - cr + 5*y4); imag = y * (5*x4 - cr + y4); break; } case 6: { final double x2 = x * x; final double y2 = y * y; final double x4 = x2 * x2; final double y4 = y2 * y2; real = (x4 * (x2 - 15*y2) + (15*x2 * y4)) - (y4 * y2); imag = (x * y) * (6 * (x4 + y4) - (20 * x2 * y2)); break; } default: { throw new IllegalArgumentException(String.valueOf(power)); } } } /** * Returns a copy of this complex number. */ @Override public Complex clone() { return new Complex(this); } /** * Returns {@code true} if this complex number has the same value than the specified one. * * @param c The complex number to compare with this object. * @return {@code true} if both objects are equal. */ public boolean equals(final Complex c) { return Double.doubleToLongBits(real) == Double.doubleToLongBits(c.real) && Double.doubleToLongBits(imag) == Double.doubleToLongBits(c.imag); } /** * Compares this complex with the specified object for equality. * * @param c The complex number to compare with this object. * @return {@code true} if both objects are equal. */ @Override public boolean equals(final Object c) { return (c instanceof Complex) && equals((Complex) c); } /** * Returns a hash value for this complex number. */ @Override public int hashCode() { final long code = Double.doubleToLongBits(real) + 31*Double.doubleToLongBits(imag); return (int) code ^ (int) (code >>> 32); } /** * Returns a string representation of this complex number. */ @Override public String toString() { return "Complex[" + real + ", " + imag + ']'; } }