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.Comparator;
012: import javolution.lang.Realtime;
013: import javolution.lang.ValueType;
014: import javolution.text.Text;
015: import javolution.text.TextBuilder;
016: import javolution.util.FastTable;
017:
018: import org.jscience.mathematics.structure.Field;
019: import org.jscience.mathematics.structure.VectorSpace;
020:
021: /**
022: * <p> This class represents an immutable element of a vector space.</p>
023: *
024: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
025: * @version 3.3, January 2, 2007
026: * @see <a href="http://en.wikipedia.org/wiki/Vector_space">
027: * Wikipedia: Vector Space</a>
028: */
029: public abstract class Vector<F extends Field<F>> implements
030: VectorSpace<Vector<F>, F>, ValueType, Realtime {
031:
032: /**
033: * Default constructor (for sub-classes).
034: */
035: protected Vector() {
036: }
037:
038: /**
039: * Returns the number of elements held by this vector.
040: *
041: * @return this vector dimension.
042: */
043: public abstract int getDimension();
044:
045: /**
046: * Returns a single element from this vector.
047: *
048: * @param i the element index (range [0..n[).
049: * @return the element at <code>i</code>.
050: * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= size())</code>
051: */
052: public abstract F get(int i);
053:
054: /**
055: * Returns the negation of this vector.
056: *
057: * @return <code>-this</code>.
058: */
059: public abstract Vector<F> opposite();
060:
061: /**
062: * Returns the sum of this vector with the one specified.
063: *
064: * @param that the vector to be added.
065: * @return <code>this + that</code>.
066: * @throws DimensionException is vectors dimensions are different.
067: */
068: public abstract Vector<F> plus(Vector<F> that);
069:
070: /**
071: * Returns the difference between this vector and the one specified.
072: *
073: * @param that the vector to be subtracted.
074: * @return <code>this - that</code>.
075: */
076: public Vector<F> minus(Vector<F> that) {
077: return this .plus(that.opposite());
078: }
079:
080: /**
081: * Returns the product of this vector with the specified coefficient.
082: *
083: * @param k the coefficient multiplier.
084: * @return <code>this · k</code>
085: */
086: public abstract Vector<F> times(F k);
087:
088: /**
089: * Returns the dot product of this vector with the one specified.
090: *
091: * @param that the vector multiplier.
092: * @return <code>this · that</code>
093: * @throws DimensionException if <code>this.dimension() != that.dimension()</code>
094: * @see <a href="http://en.wikipedia.org/wiki/Dot_product">
095: * Wikipedia: Dot Product</a>
096: */
097: public abstract F times(Vector<F> that);
098:
099: /**
100: * Returns the cross product of two 3-dimensional vectors.
101: *
102: * @param that the vector multiplier.
103: * @return <code>this x that</code>
104: * @throws DimensionException if
105: * <code>(this.getDimension() != 3) && (that.getDimension() != 3)</code>
106: */
107: public Vector<F> cross(Vector<F> that) {
108: if ((this .getDimension() != 3) || (that.getDimension() != 3))
109: throw new DimensionException(
110: "The cross product of two vectors requires "
111: + "3-dimensional vectors");
112: FastTable<F> elements = FastTable.newInstance();
113: elements.add((this .get(1).times(that.get(2))).plus((this .get(2)
114: .times(that.get(1))).opposite()));
115: elements.add((this .get(2).times(that.get(0))).plus((this .get(0)
116: .times(that.get(2))).opposite()));
117: elements.add((this .get(0).times(that.get(1))).plus((this .get(1)
118: .times(that.get(0))).opposite()));
119: DenseVector<F> V = DenseVector.valueOf(elements);
120: FastTable.recycle(elements);
121: return V;
122: }
123:
124: /**
125: * Returns the text representation of this vector.
126: *
127: * @return the text representation of this vector.
128: */
129: public Text toText() {
130: final int dimension = this .getDimension();
131: TextBuilder tmp = TextBuilder.newInstance();
132: tmp.append('{');
133: for (int i = 0; i < dimension; i++) {
134: tmp.append(get(i));
135: if (i != dimension - 1) {
136: tmp.append(", ");
137: }
138: }
139: tmp.append('}');
140: Text txt = tmp.toText();
141: TextBuilder.recycle(tmp);
142: return txt;
143: }
144:
145: /**
146: * Returns the text representation of this vector as a
147: * <code>java.lang.String</code>.
148: *
149: * @return <code>toText().toString()</code>
150: */
151: public final String toString() {
152: return toText().toString();
153: }
154:
155: /**
156: * Indicates if this vector can be considered equals to the one
157: * specified using the specified comparator when testing for
158: * element equality. The specified comparator may allow for some
159: * tolerance in the difference between the vector elements.
160: *
161: * @param that the vector to compare for equality.
162: * @param cmp the comparator to use when testing for element equality.
163: * @return <code>true</code> if this vector and the specified matrix are
164: * both vector with equal elements according to the specified
165: * comparator; <code>false</code> otherwise.
166: */
167: public boolean equals(Vector<F> that, Comparator<F> cmp) {
168: if (this == that)
169: return true;
170: final int dimension = this .getDimension();
171: if (that.getDimension() != dimension)
172: return false;
173: for (int i = dimension; --i >= 0;) {
174: if (cmp.compare(this .get(i), that.get(i)) != 0)
175: return false;
176: }
177: return true;
178: }
179:
180: /**
181: * Indicates if this vector is equal to the object specified.
182: *
183: * @param that the object to compare for equality.
184: * @return <code>true</code> if this vector and the specified object are
185: * both vectors with equal elements; <code>false</code> otherwise.
186: */
187: public boolean equals(Object that) {
188: if (this == that)
189: return true;
190: if (!(that instanceof Vector))
191: return false;
192: final int dimension = this .getDimension();
193: Vector v = (Vector) that;
194: if (v.getDimension() != dimension)
195: return false;
196: for (int i = dimension; --i >= 0;) {
197: if (!this .get(i).equals(v.get(i)))
198: return false;
199: }
200: return true;
201: }
202:
203: /**
204: * Returns a hash code value for this vector.
205: * Equals objects have equal hash codes.
206: *
207: * @return this vector hash code value.
208: * @see #equals
209: */
210: public int hashCode() {
211: final int dimension = this .getDimension();
212: int code = 0;
213: for (int i = dimension; --i >= 0;) {
214: code += get(i).hashCode();
215: }
216: return code;
217: }
218:
219: /**
220: * Returns a copy of this vector
221: * {@link javolution.context.AllocatorContext allocated}
222: * by the calling thread (possibly on the stack).
223: *
224: * @return an identical and independant copy of this matrix.
225: */
226: public abstract Vector<F> copy();
227:
228: }
|