001: /*
002: * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003: * Copyright (C) 2006 - JScience (http://jscience.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package org.jscience.mathematics.vector;
010:
011: import java.util.Iterator;
012: import java.util.List;
013: import javolution.context.ArrayFactory;
014: import javolution.xml.XMLFormat;
015: import javolution.xml.stream.XMLStreamException;
016:
017: import org.jscience.mathematics.number.Complex;
018: import org.jscience.mathematics.structure.VectorSpaceNormed;
019:
020: /**
021: * <p> This class represents an optimized {@link Vector vector} implementation
022: * for {@link Complex complex} numbers elements.</p>
023: *
024: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
025: * @version 3.3, January 2, 2007
026: */
027: public final class ComplexVector extends Vector<Complex> implements
028: VectorSpaceNormed<Vector<Complex>, Complex> {
029:
030: /**
031: * Holds the default XML representation. For example:
032: * [code]
033: * <ComplexVector dimension="2">
034: * <Complex real="1.0" imaginary="-3.0" />
035: * <Complex real="0.0" imaginary="2.0" />
036: * </ComplexVector>[/code]
037: */
038: protected static final XMLFormat<ComplexVector> XML = new XMLFormat<ComplexVector>(
039: ComplexVector.class) {
040:
041: @Override
042: public ComplexVector newInstance(Class<ComplexVector> cls,
043: InputElement xml) throws XMLStreamException {
044: int dimension = xml.getAttribute("dimension", 0);
045: ComplexVector V = FACTORY.array(dimension);
046: V._dimension = dimension;
047: return V;
048: }
049:
050: @SuppressWarnings("unchecked")
051: @Override
052: public void read(InputElement xml, ComplexVector V)
053: throws XMLStreamException {
054: for (int i = 0, n = V._dimension; i < n;) {
055: V._reals[i++] = ((Complex) xml.getNext()).doubleValue();
056: }
057: if (xml.hasNext())
058: throw new XMLStreamException("Too many elements");
059: }
060:
061: @Override
062: public void write(ComplexVector V, OutputElement xml)
063: throws XMLStreamException {
064: xml.setAttribute("dimension", V._dimension);
065: for (int i = 0, n = V._dimension; i < n;) {
066: xml.add(V.get(i++));
067: }
068: }
069: };
070:
071: /**
072: * Holds factory for vectors with variable size arrays.
073: */
074: private static final ArrayFactory<ComplexVector> FACTORY = new ArrayFactory<ComplexVector>() {
075:
076: @Override
077: protected ComplexVector create(int capacity) {
078: return new ComplexVector(capacity);
079: }
080:
081: };
082: /**
083: * Holds the dimension.
084: */
085: private int _dimension;
086:
087: /**
088: * Holds the real values.
089: */
090: private final double[] _reals;
091:
092: /**
093: * Holds the imaginary values.
094: */
095: private double[] _imags;
096:
097: /**
098: * Creates a vector of specified capacity.
099: */
100: private ComplexVector(int capacity) {
101: _reals = new double[capacity];
102: _imags = new double[capacity];
103: }
104:
105: /**
106: * Returns a new vector holding the specified complex numbers.
107: *
108: * @param elements the complex numbers elements.
109: * @return the vector having the specified complex numbers.
110: */
111: public static ComplexVector valueOf(Complex... elements) {
112: int n = elements.length;
113: ComplexVector V = FACTORY.array(n);
114: V._dimension = n;
115: for (int i = 0; i < n; i++) {
116: Complex complex = elements[i];
117: V._reals[i] = complex.getReal();
118: V._imags[i] = complex.getImaginary();
119: }
120: return V;
121: }
122:
123: /**
124: * Returns a new vector holding the elements from the specified
125: * collection.
126: *
127: * @param elements the collection of floating-points numbers.
128: * @return the vector having the specified elements.
129: */
130: public static ComplexVector valueOf(List<Complex> elements) {
131: int n = elements.size();
132: ComplexVector V = FACTORY.array(n);
133: V._dimension = n;
134: Iterator<Complex> iterator = elements.iterator();
135: for (int i = 0; i < n; i++) {
136: Complex complex = iterator.next();
137: V._reals[i] = complex.getReal();
138: V._imags[i] = complex.getImaginary();
139: }
140: return V;
141: }
142:
143: /**
144: * Returns a {@link ComplexVector} instance equivalent to the
145: * specified vector.
146: *
147: * @param that the vector to convert.
148: * @return <code>that</code> or new equivalent ComplexVector.
149: */
150: public static ComplexVector valueOf(Vector<Complex> that) {
151: if (that instanceof ComplexVector)
152: return (ComplexVector) that;
153: int n = that.getDimension();
154: ComplexVector V = FACTORY.array(n);
155: V._dimension = n;
156: for (int i = 0; i < n; i++) {
157: Complex complex = that.get(i);
158: V._reals[i] = complex.getReal();
159: V._imags[i] = complex.getImaginary();
160: }
161: return V;
162: }
163:
164: /**
165: * Returns the real value of a complex number from this vector (fast).
166: *
167: * @param i the complex number index.
168: * @return the real value of complex at <code>i</code>.
169: * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= dimension())</code>
170: */
171: public double getReal(int i) {
172: if (i >= _dimension)
173: throw new ArrayIndexOutOfBoundsException();
174: return _reals[i];
175: }
176:
177: /**
178: * Returns the imaginary value of a complex number from this vector (fast).
179: *
180: * @param i the complex number index.
181: * @return the real value of complex at <code>i</code>.
182: * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= dimension())</code>
183: */
184: public double getImaginary(int i) {
185: if (i >= _dimension)
186: throw new ArrayIndexOutOfBoundsException();
187: return _imags[i];
188: }
189:
190: /**
191: * Returns the Euclidian norm of this vector (square root of the
192: * dot product of this vector and itself).
193: *
194: * @return <code>sqrt(this ยท this)</code>.
195: */
196: public Complex norm() {
197: double normSquaredReal = 0;
198: double normSquaredImag = 0;
199: for (int i = _dimension; --i >= 0;) {
200: double real = _reals[i];
201: double imag = _imags[i];
202: normSquaredReal += real * real - imag * imag;
203: normSquaredImag += real * imag * 2.0;
204: }
205: return Complex.valueOf(normSquaredReal, normSquaredImag).sqrt();
206: }
207:
208: @Override
209: public int getDimension() {
210: return _dimension;
211: }
212:
213: @Override
214: public Complex get(int i) {
215: if (i >= _dimension)
216: throw new IndexOutOfBoundsException();
217: return Complex.valueOf(_reals[i], _imags[i]);
218: }
219:
220: @Override
221: public ComplexVector opposite() {
222: ComplexVector V = FACTORY.array(_dimension);
223: V._dimension = _dimension;
224: for (int i = 0; i < _dimension; i++) {
225: V._reals[i] = -_reals[i];
226: V._imags[i] = -_imags[i];
227: }
228: return V;
229: }
230:
231: @Override
232: public ComplexVector plus(Vector<Complex> that) {
233: ComplexVector T = ComplexVector.valueOf(that);
234: if (T._dimension != _dimension)
235: throw new DimensionException();
236: ComplexVector V = FACTORY.array(_dimension);
237: V._dimension = _dimension;
238: for (int i = 0; i < _dimension; i++) {
239: V._reals[i] = _reals[i] + T._reals[i];
240: V._imags[i] = _imags[i] + T._imags[i];
241: }
242: return V;
243: }
244:
245: @Override
246: public ComplexVector minus(Vector<Complex> that) {
247: ComplexVector T = ComplexVector.valueOf(that);
248: if (T._dimension != _dimension)
249: throw new DimensionException();
250: ComplexVector V = FACTORY.array(_dimension);
251: V._dimension = _dimension;
252: for (int i = 0; i < _dimension; i++) {
253: V._reals[i] = _reals[i] - T._reals[i];
254: V._imags[i] = _imags[i] - T._imags[i];
255: }
256: return V;
257: }
258:
259: @Override
260: public ComplexVector times(Complex k) {
261: ComplexVector V = FACTORY.array(_dimension);
262: V._dimension = _dimension;
263: for (int i = 0; i < _dimension; i++) {
264: double real = _reals[i];
265: double imag = _imags[i];
266: V._reals[i] = real * k.getReal() - imag * k.getImaginary();
267: V._imags[i] = real * k.getImaginary() + imag * k.getReal();
268: }
269: return V;
270: }
271:
272: @Override
273: public Complex times(Vector<Complex> that) {
274: ComplexVector T = ComplexVector.valueOf(that);
275: if (T._dimension != _dimension)
276: throw new DimensionException();
277: double sumReal = _reals[0] * T._reals[0] - _imags[0]
278: * T._imags[0];
279: double sumImag = _reals[0] * T._imags[0] + _imags[0]
280: * T._reals[0];
281: for (int i = 1; i < _dimension; i++) {
282: sumReal += _reals[i] * T._reals[i] - _imags[i]
283: * T._imags[i];
284: sumImag += _reals[i] * T._imags[i] + _imags[i]
285: * T._reals[i];
286: }
287: return Complex.valueOf(sumReal, sumImag);
288: }
289:
290: @Override
291: public ComplexVector copy() {
292: ComplexVector V = FACTORY.array(_dimension);
293: V._dimension = _dimension;
294: for (int i = 0; i < _dimension; i++) {
295: V._reals[i] = _reals[i];
296: V._imags[i] = _imags[i];
297: }
298: return V;
299: }
300:
301: ///////////////////////////////
302: // Package Private Utilities //
303: ///////////////////////////////
304:
305: void set(int i, Complex c) {
306: _reals[i] = c.getReal();
307: _imags[i] = c.getImaginary();
308: }
309:
310: static ComplexVector newInstance(int n) {
311: ComplexVector V = FACTORY.array(n);
312: V._dimension = n;
313: return V;
314: }
315:
316: private static final long serialVersionUID = 1L;
317:
318: }
|