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.lang.MathLib;
015: import javolution.xml.XMLFormat;
016: import javolution.xml.stream.XMLStreamException;
017:
018: import org.jscience.mathematics.number.Float64;
019: import 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: */
028: public 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,
044: InputElement xml) 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())
057: .doubleValue();
058: }
059: if (xml.hasNext())
060: throw new XMLStreamException("Too many elements");
061: }
062:
063: @Override
064: public void write(Float64Vector V, OutputElement xml)
065: throws XMLStreamException {
066: xml.setAttribute("dimension", V._dimension);
067: for (int i = 0, n = V._dimension; i < n;) {
068: xml.add(V.get(i++));
069: }
070: }
071: };
072:
073: /**
074: * Holds factory for vectors with variable size arrays.
075: */
076: private static final ArrayFactory<Float64Vector> FACTORY = 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)
216: throw new DimensionException();
217: Float64Vector V = FACTORY.array(_dimension);
218: V._dimension = _dimension;
219: for (int i = 0; i < _dimension; i++) {
220: V._values[i] = _values[i] + T._values[i];
221: }
222: return V;
223: }
224:
225: @Override
226: public Float64Vector minus(Vector<Float64> that) {
227: Float64Vector T = Float64Vector.valueOf(that);
228: if (T._dimension != _dimension)
229: throw new DimensionException();
230: Float64Vector V = FACTORY.array(_dimension);
231: V._dimension = _dimension;
232: for (int i = 0; i < _dimension; i++) {
233: V._values[i] = _values[i] - T._values[i];
234: }
235: return V;
236: }
237:
238: @Override
239: public Float64Vector times(Float64 k) {
240: Float64Vector V = FACTORY.array(_dimension);
241: V._dimension = _dimension;
242: double d = k.doubleValue();
243: for (int i = 0; i < _dimension; i++) {
244: V._values[i] = _values[i] * d;
245: }
246: return V;
247: }
248:
249: /**
250: * Equivalent to <code>this.times(Float64.valueOf(k))</code>
251: *
252: * @param k the coefficient.
253: * @return <code>this * k</code>
254: */
255: public Float64Vector times(double k) {
256: Float64Vector V = FACTORY.array(_dimension);
257: V._dimension = _dimension;
258: for (int i = 0; i < _dimension; i++) {
259: V._values[i] = _values[i] * k;
260: }
261: return V;
262: }
263:
264: @Override
265: public Float64 times(Vector<Float64> that) {
266: Float64Vector T = Float64Vector.valueOf(that);
267: if (T._dimension != _dimension)
268: throw new DimensionException();
269: double[] T_values = T._values;
270: double sum = _values[0] * T_values[0];
271: for (int i = 1; i < _dimension; i++) {
272: sum += _values[i] * T_values[i];
273: }
274: return Float64.valueOf(sum);
275: }
276:
277: @Override
278: public Float64Vector cross(Vector<Float64> that) {
279: Float64Vector T = Float64Vector.valueOf(that);
280: if ((this ._dimension != 3) || (T._dimension != 3))
281: throw new DimensionException(
282: "The cross product of two vectors requires "
283: + "3-dimensional vectors");
284: double x = _values[1] * T._values[2] - _values[2]
285: * T._values[1];
286: double y = _values[2] * T._values[0] - _values[0]
287: * T._values[2];
288: double z = _values[0] * T._values[1] - _values[1]
289: * T._values[0];
290: return Float64Vector.valueOf(x, y, z);
291: }
292:
293: @Override
294: public Float64Vector copy() {
295: Float64Vector V = FACTORY.array(_dimension);
296: V._dimension = _dimension;
297: for (int i = 0; i < _dimension; i++) {
298: V._values[i] = _values[i];
299: }
300: return V;
301: }
302:
303: ///////////////////////////////
304: // Package Private Utilities //
305: ///////////////////////////////
306:
307: static Float64Vector newInstance(int n) {
308: Float64Vector V = FACTORY.array(n);
309: V._dimension = n;
310: return V;
311: }
312:
313: void set(int i, double v) {
314: _values[i] = v;
315: }
316:
317: private static final long serialVersionUID = 1L;
318:
319: }
|