001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.math;
017:
018: import java.io.Serializable;
019: import org.opengis.util.Cloneable;
020:
021: /**
022: * A simple class for the handling of complex numbers. This is not the purpose of this class
023: * to provides a full-fledged library for complex number handling. This class exists mostly
024: * for the limited needs of some transformation methods.
025: * <p>
026: * For performance reasons, the methods in this class never create new objects. They always
027: * operate on an object specified in argument, and store the result in the object on which
028: * the method was invoked.
029: * <p>
030: * This class is final for performance reason.
031: *
032: * @since 2.2
033: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/math/Complex.java $
034: * @version $Id: Complex.java 22443 2006-10-27 20:47:22Z desruisseaux $
035: * @author Justin Deoliveira
036: * @author Martin Desruisseaux
037: */
038: public final class Complex implements Cloneable, Serializable {
039: /**
040: * For compatibility with previous versions during deserialization.
041: */
042: private static final long serialVersionUID = -8143196508298758583L;
043:
044: /**
045: * The real part of the complex number.
046: */
047: public double real;
048:
049: /**
050: * The imaginary part of the complex number.
051: */
052: public double imag;
053:
054: /**
055: * Creates a complex number initialized to (0,0).
056: */
057: public Complex() {
058: }
059:
060: /**
061: * Creates a complex number initialized to the same value than the specified one.
062: */
063: public Complex(final Complex c) {
064: real = c.real;
065: imag = c.imag;
066: }
067:
068: /**
069: * Creates a complex number initialized to the specified real and imaginary parts.
070: */
071: public Complex(final double real, final double imag) {
072: this .real = real;
073: this .imag = imag;
074: }
075:
076: /**
077: * Set this complex number to the same value than the specified one.
078: * This method computes the following:
079: *
080: * <blockquote><pre>
081: * this = c
082: * </pre></blockquote>
083: */
084: public void copy(final Complex c) {
085: real = c.real;
086: imag = c.imag;
087: }
088:
089: /**
090: * Multiplies a complex number by a scalar.
091: * This method computes the following:
092: *
093: * <blockquote><pre>
094: * this = c * s
095: * </pre></blockquote>
096: */
097: public void multiply(final Complex c, final double s) {
098: real = c.real * s;
099: imag = c.imag * s;
100: }
101:
102: /**
103: * Multplies two complex numbers.
104: * This method computes the following:
105: *
106: * <blockquote><pre>
107: * this = c1 * c2
108: * </pre></blockquote>
109: */
110: public void multiply(final Complex c1, final Complex c2) {
111: final double x1 = c1.real;
112: final double y1 = c1.imag;
113: final double x2 = c2.real;
114: final double y2 = c2.imag;
115: real = (x1 * x2) - (y1 * y2);
116: imag = (y1 * x2) + (x1 * y2);
117: }
118:
119: /**
120: * Divides one complex number by another.
121: * This method computes the following:
122: *
123: * <blockquote><pre>
124: * this = c1 / c2
125: * </pre></blockquote>
126: */
127: public void divide(final Complex c1, final Complex c2) {
128: final double x1 = c1.real;
129: final double y1 = c1.imag;
130: final double x2 = c2.real;
131: final double y2 = c2.imag;
132: final double denom = (x2 * x2) + (y2 * y2);
133: real = ((x1 * x2) + (y1 * y2)) / denom;
134: imag = ((y1 * x2) - (x1 * y2)) / denom;
135: }
136:
137: /**
138: * Adds to complex numbers.
139: * This method computes the following:
140: *
141: * <blockquote><pre>
142: * this = c1 + c2
143: * </pre></blockquote>
144: */
145: public void add(final Complex c1, final Complex c2) {
146: real = c1.real + c2.real;
147: imag = c1.imag + c2.imag;
148: }
149:
150: /**
151: * Multplies two complex numbers, and add the result to a third one.
152: * This method computes the following:
153: *
154: * <blockquote><pre>
155: * this = c0 + (c1 * c2)
156: * </pre></blockquote>
157: */
158: public void addMultiply(final Complex c0, final Complex c1,
159: final Complex c2) {
160: final double x1 = c1.real;
161: final double y1 = c1.imag;
162: final double x2 = c2.real;
163: final double y2 = c2.imag;
164: real = c0.real + ((x1 * x2) - (y1 * y2));
165: imag = c0.imag + ((y1 * x2) + (x1 * y2));
166: }
167:
168: /**
169: * Computes the integer power of a complex number up to 6.
170: * This method computes the following:
171: *
172: * <blockquote><pre>
173: * this = c ^ power
174: * </pre></blockquote>
175: */
176: public void power(final Complex c, final int power) {
177: final double x = c.real;
178: final double y = c.imag;
179: switch (power) {
180: case 0: {
181: real = 1;
182: imag = 0;
183: break;
184: }
185: case 1: {
186: real = x;
187: imag = y;
188: break;
189: }
190: case 2: {
191: real = (x * x) - (y * y);
192: imag = 2 * x * y;
193: break;
194: }
195: case 3: {
196: real = (x * x * x) - (3 * x * y * y);
197: imag = (3 * x * x * y) - (y * y * y);
198: break;
199: }
200: case 4: {
201: real = (x * x * x * x) - (6 * x * x * y * y)
202: + (y * y * y * y);
203: imag = (4 * x * x * x * y) - (4 * x * y * y * y);
204: break;
205: }
206: case 5: {
207: real = (x * x * x * x * x) - (10 * x * x * x * y * y)
208: + (5 * x * y * y * y * y);
209: imag = (5 * x * x * x * x * y) - (10 * x * x * y * y * y)
210: + (y * y * y * y * y);
211: break;
212: }
213: case 6: {
214: real = ((x * x * x * x * x * x)
215: - (15 * x * x * x * x * y * y) + (15 * x * x * y
216: * y * y * y))
217: - (y * y * y * y * y * y);
218: imag = (6 * x * x * x * x * x * y)
219: - (20 * x * x * x * y * y * y)
220: + (6 * x * y * y * y * y * y);
221: break;
222: }
223: default: {
224: throw new IllegalArgumentException(String.valueOf(power));
225: }
226: }
227: }
228:
229: /**
230: * Returns a copy of this complex number.
231: */
232: public Object clone() {
233: return new Complex(this );
234: }
235:
236: /**
237: * Returns {@code true} if this complex number has the same value than the specified one.
238: */
239: public boolean equals(final Complex c) {
240: return Double.doubleToLongBits(real) == Double
241: .doubleToLongBits(c.real)
242: && Double.doubleToLongBits(imag) == Double
243: .doubleToLongBits(c.imag);
244: }
245:
246: /**
247: * Compare this complex with the specified object for equality.
248: */
249: public boolean equals(final Object c) {
250: return (c instanceof Complex) && equals((Complex) c);
251: }
252:
253: /**
254: * Returns a hash value for this complex number.
255: */
256: public int hashCode() {
257: final long code = Double.doubleToLongBits(real) + 37
258: * Double.doubleToLongBits(imag);
259: return (int) code ^ (int) (code >>> 32);
260: }
261:
262: /**
263: * Returns a string representation of this complex number.
264: */
265: public String toString() {
266: return "Complex[" + real + ", " + imag + ']';
267: }
268: }
|