/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.math; import java.io.Serializable; import org.opengis.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. * * @since 2.2 * * @source $URL$ * @version $Id$ * @author Justin Deoliveira * @author Martin Desruisseaux */ 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. */ public Complex(final Complex c) { real = c.real; imag = c.imag; } /** * Creates a complex number initialized to the specified real and imaginary parts. */ 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: * * <blockquote><pre> * this = c * </pre></blockquote> */ public void copy(final Complex c) { real = c.real; imag = c.imag; } /** * Multiplies a complex number by a scalar. * This method computes the following: * * <blockquote><pre> * this = c * s * </pre></blockquote> */ 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: * * <blockquote><pre> * this = c1 * c2 * </pre></blockquote> */ 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: * * <blockquote><pre> * this = c1 / c2 * </pre></blockquote> */ 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: * * <blockquote><pre> * this = c1 + c2 * </pre></blockquote> */ 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: * * <blockquote><pre> * this = c0 + (c1 * c2) * </pre></blockquote> */ 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: * * <blockquote><pre> * this = c ^ power * </pre></blockquote> */ 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: { real = (x * x * x) - (3 * x * y * y); imag = (3 * x * x * y) - (y * y * y); break; } case 4: { real = (x * x * x * x) - (6 * x * x * y * y) + (y * y * y * y); imag = (4 * x * x * x * y) - (4 * x * y * y * y); break; } case 5: { real = (x * x * x * x * x) - (10 * x * x * x * y * y) + (5 * x * y * y * y * y); imag = (5 * x * x * x * x * y) - (10 * x * x * y * y * y) + (y * y * y * y * y); break; } case 6: { real = ((x * x * x * x * x * x) - (15 * x * x * x * x * y * y) + (15 * x * x * y * y * y * y)) - (y * y * y * y * y * y); imag = (6 * x * x * x * x * x * y) - (20 * x * x * x * y * y * y) + (6 * x * y * y * y * y * y); 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. */ 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. */ @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) + 37*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 + ']'; } }