summaryrefslogtreecommitdiff
path: root/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java')
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java238
1 files changed, 120 insertions, 118 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java
index 0a674d87..b0e1c78e 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java
@@ -27,8 +27,6 @@ import java.util.Arrays;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
/**
* Provides a vector object that encapsulates an m x 1 - matrix object.
@@ -37,7 +35,7 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter
*
* @apiviz.landmark
*/
-public class Vector implements NumberVector<Vector, Double> {
+public class Vector implements NumberVector<Double> {
/**
* Array for internal storage of elements.
*
@@ -46,6 +44,21 @@ public class Vector implements NumberVector<Vector, Double> {
protected final double[] elements;
/**
+ * Error message (in assertions!) when vector dimensionalities do not agree.
+ */
+ public static final String ERR_VEC_DIMENSIONS = "Vector dimensions do not agree.";
+
+ /**
+ * Error message (in assertions!) when matrix dimensionalities do not agree.
+ */
+ public static final String ERR_MATRIX_INNERDIM = "Matrix inner dimensions do not agree.";
+
+ /**
+ * Error message (in assertions!) when dimensionalities do not agree.
+ */
+ private static final String ERR_DIMENSIONS = "Dimensionalities do not agree.";
+
+ /**
* Construct a vector from a given array.
*
* @param values array of doubles
@@ -64,7 +77,7 @@ public class Vector implements NumberVector<Vector, Double> {
}
/**
- * Returns a randomly created vector of length 1.0
+ * Returns a randomly created vector of length 1.0.
*
* @param dimensionality dimensionality
* @return the dimensionality of the vector
@@ -72,13 +85,13 @@ public class Vector implements NumberVector<Vector, Double> {
public static final Vector randomNormalizedVector(final int dimensionality) {
final Vector v = new Vector(dimensionality);
double norm = 0;
- while(norm <= 0) {
- for(int i = 0; i < dimensionality; i++) {
+ while (norm <= 0) {
+ for (int i = 0; i < dimensionality; i++) {
v.elements[i] = Math.random();
}
norm = v.euclideanLength();
}
- for(int row = 0; row < dimensionality; row++) {
+ for (int row = 0; row < dimensionality; row++) {
v.elements[row] /= norm;
}
return v;
@@ -106,9 +119,6 @@ public class Vector implements NumberVector<Vector, Double> {
return new Vector(elements.clone());
}
- /**
- * Clone the Vector object.
- */
@Override
public Vector clone() {
return this.copy();
@@ -173,9 +183,9 @@ public class Vector implements NumberVector<Vector, Double> {
* @return the resulting vector
*/
public final Vector plus(final Vector v) {
- assert (this.elements.length == v.elements.length) : "Vector dimensions must agree.";
+ assert (this.elements.length == v.elements.length) : ERR_VEC_DIMENSIONS;
final Vector result = new Vector(elements.length);
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
result.elements[i] = elements[i] + v.elements[i];
}
return result;
@@ -190,39 +200,39 @@ public class Vector implements NumberVector<Vector, Double> {
* @return the resulting vector
*/
public final Vector plusTimes(final Vector v, final double s) {
- assert (this.elements.length == v.elements.length) : "Vector dimensions must agree.";
+ assert (this.elements.length == v.elements.length) : ERR_VEC_DIMENSIONS;
final Vector result = new Vector(elements.length);
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
result.elements[i] = elements[i] + v.elements[i] * s;
}
return result;
}
/**
- * A = A + B
+ * a = a + b.
*
- * @param B another matrix
- * @return A + B in this Matrix
+ * @param b another vector
+ * @return a + b in this vector
*/
- public final Vector plusEquals(final Vector B) {
- assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
- for(int i = 0; i < elements.length; i++) {
- elements[i] += B.elements[i];
+ public final Vector plusEquals(final Vector b) {
+ assert (this.elements.length == b.elements.length) : ERR_VEC_DIMENSIONS;
+ for (int i = 0; i < elements.length; i++) {
+ elements[i] += b.elements[i];
}
return this;
}
/**
- * A = A + s * B
+ * a = a + s * b.
*
- * @param B another matrix
+ * @param b another vector
* @param s Scalar
- * @return A + s * B in this Matrix
+ * @return a + s * b in this vector
*/
- public final Vector plusTimesEquals(final Vector B, final double s) {
- assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
- for(int i = 0; i < elements.length; i++) {
- elements[i] += s * B.elements[i];
+ public final Vector plusTimesEquals(final Vector b, final double s) {
+ assert (this.elements.length == b.elements.length) : ERR_VEC_DIMENSIONS;
+ for (int i = 0; i < elements.length; i++) {
+ elements[i] += s * b.elements[i];
}
return this;
}
@@ -234,7 +244,7 @@ public class Vector implements NumberVector<Vector, Double> {
* @return Modified vector
*/
public final Vector plusEquals(final double d) {
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
elements[i] += d;
}
return this;
@@ -248,7 +258,7 @@ public class Vector implements NumberVector<Vector, Double> {
*/
public final Vector minus(final Vector v) {
final Vector sub = new Vector(elements.length);
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
sub.elements[i] = elements[i] - v.elements[i];
}
return sub;
@@ -263,37 +273,37 @@ public class Vector implements NumberVector<Vector, Double> {
*/
public final Vector minusTimes(final Vector v, final double s) {
final Vector sub = new Vector(elements.length);
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
sub.elements[i] = elements[i] - v.elements[i] * s;
}
return sub;
}
/**
- * A = A - B
+ * a = a - b.
*
- * @param B another matrix
- * @return A - B in this Matrix
+ * @param b another vector
+ * @return a - b in this vector
*/
- public final Vector minusEquals(final Vector B) {
- assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
- for(int i = 0; i < elements.length; i++) {
- elements[i] -= B.elements[i];
+ public final Vector minusEquals(final Vector b) {
+ assert (this.elements.length == b.elements.length) : ERR_VEC_DIMENSIONS;
+ for (int i = 0; i < elements.length; i++) {
+ elements[i] -= b.elements[i];
}
return this;
}
/**
- * A = A - s * B
+ * a = a - s * b.
*
- * @param B another matrix
+ * @param b another vector
* @param s Scalar
- * @return A - s * B in this Matrix
+ * @return a - s * b in this vector
*/
- public final Vector minusTimesEquals(final Vector B, final double s) {
- assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
- for(int i = 0; i < elements.length; i++) {
- elements[i] -= s * B.elements[i];
+ public final Vector minusTimesEquals(final Vector b, final double s) {
+ assert (this.elements.length == b.elements.length) : ERR_VEC_DIMENSIONS;
+ for (int i = 0; i < elements.length; i++) {
+ elements[i] -= s * b.elements[i];
}
return this;
}
@@ -305,7 +315,7 @@ public class Vector implements NumberVector<Vector, Double> {
* @return Modified vector
*/
public final Vector minusEquals(final double d) {
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
elements[i] -= d;
}
return this;
@@ -320,36 +330,36 @@ public class Vector implements NumberVector<Vector, Double> {
*/
public final Vector times(final double s) {
final Vector v = new Vector(elements.length);
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
v.elements[i] = elements[i] * s;
}
return v;
}
/**
- * Multiply a matrix by a scalar in place, A = s*A
+ * Multiply a matrix by a scalar in place, A = s*A.
*
* @param s scalar
* @return replace A by s*A
*/
public final Vector timesEquals(final double s) {
- for(int i = 0; i < elements.length; i++) {
+ for (int i = 0; i < elements.length; i++) {
elements[i] *= s;
}
return this;
}
/**
- * Linear algebraic matrix multiplication, A * B
+ * Linear algebraic matrix multiplication, A * B.
*
* @param B another matrix
* @return Matrix product, A * B
*/
public final Matrix times(final Matrix B) {
- assert (B.elements.length == 1) : "Matrix inner dimensions must agree.";
+ assert (B.elements.length == 1) : ERR_MATRIX_INNERDIM;
final Matrix X = new Matrix(this.elements.length, B.columndimension);
- for(int j = 0; j < B.columndimension; j++) {
- for(int i = 0; i < this.elements.length; i++) {
+ for (int j = 0; j < B.columndimension; j++) {
+ for (int i = 0; i < this.elements.length; i++) {
X.elements[i][j] = elements[i] * B.elements[0][j];
}
}
@@ -357,18 +367,18 @@ public class Vector implements NumberVector<Vector, Double> {
}
/**
- * Linear algebraic matrix multiplication, A<sup>T</sup> * B
+ * Linear algebraic matrix multiplication, A<sup>T</sup> * B.
*
* @param B another matrix
* @return Matrix product, A<sup>T</sup> * B
*/
public final Matrix transposeTimes(final Matrix B) {
- assert (B.elements.length == this.elements.length) : "Matrix inner dimensions must agree.";
+ assert (B.elements.length == this.elements.length) : ERR_MATRIX_INNERDIM;
final Matrix X = new Matrix(1, B.columndimension);
- for(int j = 0; j < B.columndimension; j++) {
+ for (int j = 0; j < B.columndimension; j++) {
// multiply it with each row from A
double s = 0;
- for(int k = 0; k < this.elements.length; k++) {
+ for (int k = 0; k < this.elements.length; k++) {
s += this.elements[k] * B.elements[k][j];
}
X.elements[0][j] = s;
@@ -377,19 +387,19 @@ public class Vector implements NumberVector<Vector, Double> {
}
/**
- * Linear algebraic matrix multiplication, a<sup>T</sup> * B * c
+ * Linear algebraic matrix multiplication, a<sup>T</sup> * B * c.
*
* @param B matrix
* @param c vector on the right
- * @return Matrix product, a<sup>T</sup> * B
+ * @return Matrix product, a<sup>T</sup> * B * c
*/
public final double transposeTimesTimes(final Matrix B, final Vector c) {
- assert (B.elements.length == this.elements.length) : "Matrix inner dimensions must agree.";
+ assert (B.elements.length == this.elements.length) : ERR_MATRIX_INNERDIM;
double sum = 0.0;
- for(int j = 0; j < B.columndimension; j++) {
+ for (int j = 0; j < B.columndimension; j++) {
// multiply it with each row from A
double s = 0;
- for(int k = 0; k < this.elements.length; k++) {
+ for (int k = 0; k < this.elements.length; k++) {
s += this.elements[k] * B.elements[k][j];
}
sum += s * c.elements[j];
@@ -398,31 +408,31 @@ public class Vector implements NumberVector<Vector, Double> {
}
/**
- * Linear algebraic matrix multiplication, A<sup>T</sup> * B
+ * Linear algebraic matrix multiplication, A<sup>T</sup> * B.
*
* @param B another vector
* @return Matrix product, A<sup>T</sup> * B
*/
public final double transposeTimes(final Vector B) {
- assert (B.elements.length == this.elements.length) : "Matrix inner dimensions must agree.";
+ assert (B.elements.length == this.elements.length) : ERR_MATRIX_INNERDIM;
double s = 0;
- for(int k = 0; k < this.elements.length; k++) {
+ for (int k = 0; k < this.elements.length; k++) {
s += this.elements[k] * B.elements[k];
}
return s;
}
/**
- * Linear algebraic matrix multiplication, A * B^T
+ * Linear algebraic matrix multiplication, A * B^T.
*
* @param B another matrix
* @return Matrix product, A * B^T
*/
public final Matrix timesTranspose(final Matrix B) {
- assert (B.columndimension == 1) : "Matrix inner dimensions must agree.";
+ assert (B.columndimension == 1) : ERR_MATRIX_INNERDIM;
final Matrix X = new Matrix(this.elements.length, B.elements.length);
- for(int j = 0; j < B.elements.length; j++) {
- for(int i = 0; i < this.elements.length; i++) {
+ for (int j = 0; j < B.elements.length; j++) {
+ for (int i = 0; i < this.elements.length; i++) {
X.elements[i][j] = elements[i] * B.elements[j][0];
}
}
@@ -430,15 +440,15 @@ public class Vector implements NumberVector<Vector, Double> {
}
/**
- * Linear algebraic matrix multiplication, A * B^T
+ * Linear algebraic matrix multiplication, A * B^T.
*
* @param B another matrix
* @return Matrix product, A * B^T
*/
public final Matrix timesTranspose(final Vector B) {
final Matrix X = new Matrix(this.elements.length, B.elements.length);
- for(int j = 0; j < B.elements.length; j++) {
- for(int i = 0; i < this.elements.length; i++) {
+ for (int j = 0; j < B.elements.length; j++) {
+ for (int i = 0; i < this.elements.length; i++) {
X.elements[i][j] = elements[i] * B.elements[j];
}
}
@@ -452,7 +462,7 @@ public class Vector implements NumberVector<Vector, Double> {
*/
public final double euclideanLength() {
double acc = 0.0;
- for(int row = 0; row < elements.length; row++) {
+ for (int row = 0; row < elements.length; row++) {
final double v = elements[row];
acc += v * v;
}
@@ -461,11 +471,13 @@ public class Vector implements NumberVector<Vector, Double> {
/**
* Normalizes this vector to the length of 1.0.
+ *
+ * @return this vector
*/
public final Vector normalize() {
double norm = euclideanLength();
- if(norm != 0) {
- for(int row = 0; row < elements.length; row++) {
+ if (norm != 0) {
+ for (int row = 0; row < elements.length; row++) {
elements[row] /= norm;
}
}
@@ -480,9 +492,9 @@ public class Vector implements NumberVector<Vector, Double> {
* @return the projection of p into the subspace formed by v
*/
public final Vector projection(final Matrix v) {
- assert (elements.length == v.elements.length) : "p and v differ in row dimensionality!";
+ assert (elements.length == v.elements.length) : ERR_DIMENSIONS;
Vector sum = new Vector(elements.length);
- for(int i = 0; i < v.columndimension; i++) {
+ for (int i = 0; i < v.columndimension; i++) {
// TODO: optimize - copy less?
Vector v_i = v.getCol(i);
sum.plusTimesEquals(v_i, this.transposeTimes(v_i));
@@ -497,17 +509,17 @@ public class Vector implements NumberVector<Vector, Double> {
@Override
public boolean equals(Object obj) {
- if(this == obj) {
+ if (this == obj) {
return true;
}
- if(obj == null) {
+ if (obj == null) {
return false;
}
- if(getClass() != obj.getClass()) {
+ if (getClass() != obj.getClass()) {
return false;
}
final Vector other = (Vector) obj;
- if(this.elements.length != other.elements.length) {
+ if (this.elements.length != other.elements.length) {
return false;
}
return Arrays.equals(this.elements, other.elements);
@@ -525,7 +537,7 @@ public class Vector implements NumberVector<Vector, Double> {
/**
* Returns a string representation of this vector without adding extra
- * whitespace
+ * whitespace.
*
* @return a string representation of this vector.
*/
@@ -553,81 +565,71 @@ public class Vector implements NumberVector<Vector, Double> {
return this;
}
+ /**
+ * Cross product for 3d vectors, i.e. <code>this x other</code>
+ *
+ * @param other Other vector
+ * @return Cross product of this vector and the other vector
+ */
+ public Vector cross3D(Vector other) {
+ assert (elements.length == 3 && other.elements.length == 3);
+ Vector out = new Vector(3);
+ out.elements[0] = (elements[1] * other.elements[2]) - (elements[2] * other.elements[1]);
+ out.elements[1] = (elements[2] * other.elements[0]) - (elements[0] * other.elements[2]);
+ out.elements[2] = (elements[0] * other.elements[1]) - (elements[1] * other.elements[0]);
+ return out;
+ }
+
// ////// NumberVector API. A bit hackish. :-(
@Override
public double getMin(int dimension) {
- return elements[dimension - 1];
+ return elements[dimension];
}
@Override
public double getMax(int dimension) {
- return elements[dimension - 1];
+ return elements[dimension];
}
@Override
+ @Deprecated
public Double getValue(int dimension) {
- return elements[dimension - 1];
+ return Double.valueOf(elements[dimension]);
}
@Override
public double doubleValue(int dimension) {
- return elements[dimension - 1];
+ return elements[dimension];
}
@Override
public float floatValue(int dimension) {
- return (float) elements[dimension - 1];
+ return (float) elements[dimension];
}
@Override
public int intValue(int dimension) {
- return (int) elements[dimension - 1];
+ return (int) elements[dimension];
}
@Override
public long longValue(int dimension) {
- return (long) elements[dimension - 1];
+ return (long) elements[dimension];
}
@Override
public short shortValue(int dimension) {
- return (short) elements[dimension - 1];
+ return (short) elements[dimension];
}
@Override
public byte byteValue(int dimension) {
- return (byte) elements[dimension - 1];
+ return (byte) elements[dimension];
}
@Override
public Vector getColumnVector() {
return copy();
}
-
- @Override
- public Vector newNumberVector(double[] values) {
- return new Vector(values);
- }
-
- @Override
- public <A> Vector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
- double[] raw = new double[adapter.size(array)];
- for(int i = 0; i < raw.length; i++) {
- raw[i] = adapter.getDouble(array, i);
- }
- return new Vector(raw);
- }
-
- @Override
- public <A> Vector newFeatureVector(A array, ArrayAdapter<Double, A> adapter) {
- if(adapter instanceof NumberArrayAdapter) {
- return newNumberVector(array, (NumberArrayAdapter<?, A>) adapter);
- }
- double[] raw = new double[adapter.size(array)];
- for(int i = 0; i < raw.length; i++) {
- raw[i] = adapter.get(array, i);
- }
- return new Vector(raw);
- }
-} \ No newline at end of file
+}