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 */
009package org.jscience.mathematics.vector;
010
011import java.util.Iterator;
012import java.util.List;
013import javolution.context.ArrayFactory;
014import javolution.xml.XMLFormat;
015import javolution.xml.stream.XMLStreamException;
016
017import org.jscience.mathematics.number.Complex;
018import 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 */
027public 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 
075         = new ArrayFactory<ComplexVector>() {
076
077        @Override
078        protected ComplexVector create(int capacity) {
079            return new ComplexVector(capacity);
080        }
081
082    };
083    /**
084     * Holds the dimension.
085     */
086    private int _dimension;
087
088    /**
089     * Holds the real values.
090     */
091    private final double[] _reals;
092
093    /**
094     * Holds the imaginary values.
095     */
096    private double[] _imags;
097
098    /**
099     * Creates a vector of specified capacity.
100     */
101    private ComplexVector(int capacity) {
102        _reals = new double[capacity];
103        _imags = new double[capacity];
104    }    
105    
106    /**
107     * Returns a new vector holding the specified complex numbers.
108     *
109     * @param elements the complex numbers elements.
110     * @return the vector having the specified complex numbers.
111     */
112    public static ComplexVector valueOf(Complex... elements) {
113        int n = elements.length;
114        ComplexVector V = FACTORY.array(n);
115        V._dimension = n;
116        for (int i = 0; i < n; i++) {
117            Complex complex = elements[i];
118            V._reals[i] = complex.getReal();
119            V._imags[i] = complex.getImaginary();
120        }
121        return V;
122    }
123
124    /**
125     * Returns a new vector holding the elements from the specified 
126     * collection.
127     *
128     * @param elements the collection of floating-points numbers.
129     * @return the vector having the specified elements.
130     */
131    public static ComplexVector valueOf(List<Complex> elements) {
132        int n = elements.size();
133        ComplexVector V = FACTORY.array(n);
134        V._dimension = n;
135        Iterator<Complex> iterator = elements.iterator();
136        for (int i = 0; i < n; i++) {
137            Complex complex = iterator.next();
138            V._reals[i] = complex.getReal();
139            V._imags[i] = complex.getImaginary();
140        }
141        return V;
142    }
143
144    /**
145     * Returns a {@link ComplexVector} instance equivalent to the 
146     * specified vector.
147     *
148     * @param that the vector to convert. 
149     * @return <code>that</code> or new equivalent ComplexVector.
150     */
151    public static ComplexVector valueOf(Vector<Complex> that) {
152        if (that instanceof ComplexVector)
153            return (ComplexVector) that;
154        int n = that.getDimension();
155        ComplexVector V = FACTORY.array(n);
156        V._dimension = n;
157        for (int i = 0; i < n; i++) {
158            Complex complex = that.get(i);
159            V._reals[i] = complex.getReal();
160            V._imags[i] = complex.getImaginary();
161        }
162        return V;
163    }
164
165    /**
166     * Returns the real value of a complex number from this vector (fast).
167     *
168     * @param  i the complex number index.
169     * @return the real value of complex at <code>i</code>.
170     * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= dimension())</code>
171     */
172    public double getReal(int i) {
173        if (i >= _dimension)
174            throw new ArrayIndexOutOfBoundsException();
175        return _reals[i];
176    }
177
178    /**
179     * Returns the imaginary value of a complex number from this vector (fast).
180     *
181     * @param  i the complex number index.
182     * @return the real value of complex at <code>i</code>.
183     * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= dimension())</code>
184     */
185    public double getImaginary(int i) {
186        if (i >= _dimension)
187            throw new ArrayIndexOutOfBoundsException();
188        return _imags[i];
189    }
190
191    /**
192     * Returns the Euclidian norm of this vector (square root of the 
193     * dot product of this vector and itself).
194     *
195     * @return <code>sqrt(this ยท this)</code>.
196     */
197    public Complex norm() {
198        double normSquaredReal = 0;
199        double normSquaredImag = 0;
200        for (int i = _dimension; --i >= 0;) {
201            double real = _reals[i];
202            double imag = _imags[i];
203            normSquaredReal += real * real - imag * imag;
204            normSquaredImag += real * imag * 2.0;
205        }
206        return Complex.valueOf(normSquaredReal, normSquaredImag).sqrt();
207    }
208
209    @Override
210    public int getDimension() {
211        return _dimension;
212    }
213
214    @Override
215    public Complex get(int i) {
216        if (i >= _dimension)
217            throw new IndexOutOfBoundsException();
218        return Complex.valueOf(_reals[i], _imags[i]);
219    }
220
221    @Override
222    public ComplexVector opposite() {
223        ComplexVector V = FACTORY.array(_dimension);
224        V._dimension = _dimension;
225        for (int i = 0; i < _dimension; i++) {
226            V._reals[i] = -_reals[i];
227            V._imags[i] = -_imags[i];
228        }
229        return V;
230    }
231
232    @Override
233    public ComplexVector plus(Vector<Complex> that) {
234        ComplexVector T = ComplexVector.valueOf(that);
235        if (T._dimension != _dimension)
236            throw new DimensionException();
237        ComplexVector V = FACTORY.array(_dimension);
238        V._dimension = _dimension;
239        for (int i = 0; i < _dimension; i++) {
240            V._reals[i] = _reals[i] + T._reals[i];
241            V._imags[i] = _imags[i] + T._imags[i];
242        }
243        return V;
244    }
245
246    @Override
247    public ComplexVector minus(Vector<Complex> that) {
248        ComplexVector T = ComplexVector.valueOf(that);
249        if (T._dimension != _dimension)
250            throw new DimensionException();
251        ComplexVector V = FACTORY.array(_dimension);
252        V._dimension = _dimension;
253        for (int i = 0; i < _dimension; i++) {
254            V._reals[i] = _reals[i] - T._reals[i];
255            V._imags[i] = _imags[i] - T._imags[i];
256        }
257        return V;
258    }
259
260    @Override
261    public ComplexVector times(Complex k) {
262        ComplexVector V = FACTORY.array(_dimension);
263        V._dimension = _dimension;
264        for (int i = 0; i < _dimension; i++) {
265            double real = _reals[i];
266            double imag = _imags[i];
267            V._reals[i] = real * k.getReal() - imag * k.getImaginary();
268            V._imags[i] = real * k.getImaginary() + imag * k.getReal();
269        }
270        return V;
271    }
272
273    @Override
274    public Complex times(Vector<Complex> that) {
275        ComplexVector T = ComplexVector.valueOf(that);
276        if (T._dimension != _dimension)
277            throw new DimensionException();
278        double sumReal = _reals[0] * T._reals[0] - _imags[0] * T._imags[0];
279        double sumImag = _reals[0] * T._imags[0] + _imags[0] * T._reals[0];
280        for (int i = 1; i < _dimension; i++) {
281            sumReal += _reals[i] * T._reals[i] - _imags[i] * T._imags[i];
282            sumImag += _reals[i] * T._imags[i] + _imags[i] * T._reals[i];
283        }
284        return Complex.valueOf(sumReal, sumImag);
285    }
286
287    @Override
288    public ComplexVector copy() {
289        ComplexVector V = FACTORY.array(_dimension);
290        V._dimension = _dimension;
291        for (int i = 0; i < _dimension; i++) {
292            V._reals[i] = _reals[i];
293            V._imags[i] = _imags[i];
294        }
295        return V;
296    }
297    ///////////////////////////////
298    // Package Private Utilities //
299    ///////////////////////////////
300    
301    void set(int i, Complex c) {
302         _reals[i] = c.getReal();
303         _imags[i] = c.getImaginary();
304    }    
305
306    static ComplexVector newInstance(int n) {
307        ComplexVector V = FACTORY.array(n);
308        V._dimension = n;
309        return V;
310    }
311    
312    private static final long serialVersionUID = 1L;
313
314}