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