Support for one dimensional vectors has been added to the linear algebra

package with a RealVector interface, a RealVectorImpl default implementation
using a single double array to store elements and a RealVectorFormat class for
input/output.


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0@680166 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2008-07-27 19:15:22 +00:00
parent 6ef68ad4a9
commit b47b287663
13 changed files with 4199 additions and 19 deletions

View File

@ -82,6 +82,11 @@
<Method name="getValues" params="" returns="double[]" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.apache.commons.math.linear.RealVectorImpl"/>
<Method name="getDataRef" params="" returns="double[]" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<!-- The following cases are intentional unit tests for null parameters -->
<Match>

View File

@ -126,6 +126,9 @@
<contributor>
<name>Todd C. Parnell</name>
</contributor>
<contributor>
<name>Andreas Rieger</name>
</contributor>
<contributor>
<name>Joni Salonen</name>
</contributor>

View File

@ -148,6 +148,26 @@ public interface RealMatrix {
* @throws MatrixIndexException if the specified column index is invalid
*/
RealMatrix getColumnMatrix(int column) throws MatrixIndexException;
/**
* Returns the entries in row number <code>row</code>
* as a vector. Row indices start at 0.
*
* @param row the row to be fetched
* @return row vector
* @throws MatrixIndexException if the specified row index is invalid
*/
RealVector getRowVector(int row) throws MatrixIndexException;
/**
* Returns the entries in column number <code>column</code>
* as a column vector. Column indices start at 0.
*
* @param column the column to be fetched
* @return column vector
* @throws MatrixIndexException if the specified column index is invalid
*/
RealVector getColumnVector(int column) throws MatrixIndexException;
/**
* Returns the entries in row number <code>row</code> as an array.
@ -255,6 +275,15 @@ public interface RealMatrix {
*/
double[] operate(double[] v) throws IllegalArgumentException;
/**
* Returns the result of multiplying this by the vector <code>v</code>.
*
* @param v the vector to operate on
* @return this*v
* @throws IllegalArgumentException if columnDimension != v.size()
*/
RealVector operate(RealVector v) throws IllegalArgumentException;
/**
* Returns the (row) vector result of premultiplying this by the vector <code>v</code>.
*
@ -264,6 +293,15 @@ public interface RealMatrix {
*/
double[] preMultiply(double[] v) throws IllegalArgumentException;
/**
* Returns the (row) vector result of premultiplying this by the vector <code>v</code>.
*
* @param v the row vector to premultiply by
* @return v*this
* @throws IllegalArgumentException if rowDimension != v.size()
*/
RealVector preMultiply(RealVector v) throws IllegalArgumentException;
/**
* Returns the solution vector for a linear system with coefficient
* matrix = this and constant vector = <code>b</code>.
@ -275,6 +313,17 @@ public interface RealMatrix {
*/
double[] solve(double[] b) throws IllegalArgumentException, InvalidMatrixException;
/**
* Returns the solution vector for a linear system with coefficient
* matrix = this and constant vector = <code>b</code>.
*
* @param b constant vector
* @return vector of solution values to AX = b, where A is *this
* @throws IllegalArgumentException if this.rowDimension != b.length
* @throws InvalidMatrixException if this matrix is not square or is singular
*/
RealVector solve(RealVector b) throws IllegalArgumentException, InvalidMatrixException;
/**
* Returns a matrix of (column) solution vectors for linear systems with
* coefficient matrix = this and constant vectors = columns of
@ -287,5 +336,5 @@ public interface RealMatrix {
* @throws InvalidMatrixException if this matrix is not square or is singular
*/
RealMatrix solve(RealMatrix b) throws IllegalArgumentException, InvalidMatrixException;
}
}

View File

@ -52,7 +52,7 @@ import org.apache.commons.math.util.MathUtils;
public class RealMatrixImpl implements RealMatrix, Serializable {
/** Serializable version identifier */
private static final long serialVersionUID = -4828886979278117018L;
private static final long serialVersionUID = 4970229902484487012L;
/** Entries of the matrix */
protected double data[][] = null;
@ -600,7 +600,17 @@ public class RealMatrixImpl implements RealMatrix, Serializable {
return new RealMatrixImpl(out, false);
}
/**
/** {@inheritDoc} */
public RealVector getColumnVector(int column) throws MatrixIndexException {
return new RealVectorImpl(getColumn(column), false);
}
/** {@inheritDoc} */
public RealVector getRowVector(int row) throws MatrixIndexException {
return new RealVectorImpl(getRow(row), false);
}
/**
* Returns the entries in row number <code>row</code> as an array.
* <p>
* Row indices start at 0. A <code>MatrixIndexException</code> is thrown
@ -788,6 +798,40 @@ public class RealMatrixImpl implements RealMatrix, Serializable {
return out;
}
/** {@inheritDoc} */
public RealVector operate(RealVector v) throws IllegalArgumentException {
try {
return operate((RealVectorImpl) v);
} catch (ClassCastException cce) {
final int nRows = this.getRowDimension();
final int nCols = this.getColumnDimension();
if (v.getDimension() != nCols) {
throw new IllegalArgumentException("vector has wrong length");
}
final double[] out = new double[nRows];
for (int row = 0; row < nRows; row++) {
final double[] dataRow = data[row];
double sum = 0;
for (int i = 0; i < nCols; i++) {
sum += dataRow[i] * v.getEntry(i);
}
out[row] = sum;
}
return new RealVectorImpl(out, false);
}
}
/**
* Returns the result of multiplying this by the vector <code>v</code>.
*
* @param v the vector to operate on
* @return this*v
* @throws IllegalArgumentException if columnDimension != v.size()
*/
public RealVectorImpl operate(RealVectorImpl v) throws IllegalArgumentException {
return new RealVectorImpl(operate(v.getDataRef()), false);
}
/**
* @param v vector to premultiply by
* @throws IllegalArgumentException if rowDimension != v.length
@ -810,6 +854,39 @@ public class RealMatrixImpl implements RealMatrix, Serializable {
return out;
}
/** {@inheritDoc} */
public RealVector preMultiply(RealVector v) throws IllegalArgumentException {
try {
return preMultiply((RealVectorImpl) v);
} catch (ClassCastException cce) {
final int nRows = this.getRowDimension();
if (v.getDimension() != nRows) {
throw new IllegalArgumentException("vector has wrong length");
}
final int nCols = this.getColumnDimension();
final double[] out = new double[nCols];
for (int col = 0; col < nCols; col++) {
double sum = 0;
for (int i = 0; i < nRows; i++) {
sum += data[i][col] * v.getEntry(i);
}
out[col] = sum;
}
return new RealVectorImpl(out, false);
}
}
/**
* Returns the (row) vector result of premultiplying this by the vector <code>v</code>.
*
* @param v the row vector to premultiply by
* @return v*this
* @throws IllegalArgumentException if rowDimension != v.size()
*/
RealVectorImpl preMultiply(RealVectorImpl v) throws IllegalArgumentException {
return new RealVectorImpl(preMultiply(v.getDataRef()), false);
}
/**
* Returns a matrix of (column) solution vectors for linear systems with
* coefficient matrix = this and constant vectors = columns of
@ -822,17 +899,105 @@ public class RealMatrixImpl implements RealMatrix, Serializable {
* @throws InvalidMatrixException if this matrix is not square or is singular
*/
public double[] solve(double[] b) throws IllegalArgumentException, InvalidMatrixException {
final int nRows = this.getRowDimension();
final int nCol = this.getColumnDimension();
if (b.length != nRows) {
throw new IllegalArgumentException("constant vector has wrong length");
}
final RealMatrix bMatrix = new RealMatrixImpl(b);
final double[][] solution = ((RealMatrixImpl) (solve(bMatrix))).getDataRef();
final double[] out = new double[nRows];
for (int row = 0; row < nRows; row++) {
out[row] = solution[row][0];
if (!isSquare()) {
throw new InvalidMatrixException("coefficient matrix is not square");
}
return out;
if (isSingular()) { // side effect: compute LU decomp
throw new InvalidMatrixException("Matrix is singular.");
}
final double[] bp = new double[nRows];
// Apply permutations to b
for (int row = 0; row < nRows; row++) {
bp[row] = b[permutation[row]];
}
// Solve LY = b
for (int col = 0; col < nCol; col++) {
for (int i = col + 1; i < nCol; i++) {
bp[i] -= bp[col] * lu[i][col];
}
}
// Solve UX = Y
for (int col = nCol - 1; col >= 0; col--) {
bp[col] /= lu[col][col];
for (int i = 0; i < col; i++) {
bp[i] -= bp[col] * lu[i][col];
}
}
return bp;
}
/** {@inheritDoc} */
public RealVector solve(RealVector b)
throws IllegalArgumentException, InvalidMatrixException {
try {
return solve((RealVectorImpl) b);
} catch (ClassCastException cce) {
final int nRows = this.getRowDimension();
final int nCol = this.getColumnDimension();
if (b.getDimension() != nRows) {
throw new IllegalArgumentException("constant vector has wrong length");
}
if (!isSquare()) {
throw new InvalidMatrixException("coefficient matrix is not square");
}
if (isSingular()) { // side effect: compute LU decomp
throw new InvalidMatrixException("Matrix is singular.");
}
final double[] bp = new double[nRows];
// Apply permutations to b
for (int row = 0; row < nRows; row++) {
bp[row] = b.getEntry(permutation[row]);
}
// Solve LY = b
for (int col = 0; col < nCol; col++) {
for (int i = col + 1; i < nCol; i++) {
bp[i] -= bp[col] * lu[i][col];
}
}
// Solve UX = Y
for (int col = nCol - 1; col >= 0; col--) {
bp[col] /= lu[col][col];
for (int i = 0; i < col; i++) {
bp[i] -= bp[col] * lu[i][col];
}
}
return new RealVectorImpl(bp, false);
}
}
/**
* Returns the solution vector for a linear system with coefficient
* matrix = this and constant vector = <code>b</code>.
*
* @param b constant vector
* @return vector of solution values to AX = b, where A is *this
* @throws IllegalArgumentException if this.rowDimension != b.length
* @throws InvalidMatrixException if this matrix is not square or is singular
*/
RealVectorImpl solve(RealVectorImpl b)
throws IllegalArgumentException, InvalidMatrixException {
return new RealVectorImpl(solve(b.getDataRef()), false);
}
/**
@ -865,18 +1030,20 @@ public class RealMatrixImpl implements RealMatrix, Serializable {
final double[][] bp = new double[nRowB][nColB];
for (int row = 0; row < nRowB; row++) {
final double[] bpRow = bp[row];
final int pRow = permutation[row];
for (int col = 0; col < nColB; col++) {
bpRow[col] = b.getEntry(permutation[row], col);
bpRow[col] = b.getEntry(pRow, col);
}
}
// Solve LY = b
for (int col = 0; col < nCol; col++) {
final double[] bpCol = bp[col];
for (int i = col + 1; i < nCol; i++) {
final double[] bpI = bp[i];
final double[] luI = lu[i];
final double luICol = lu[i][col];
for (int j = 0; j < nColB; j++) {
bpI[j] -= bp[col][j] * luI[col];
bpI[j] -= bpCol[j] * luICol;
}
}
}
@ -890,9 +1057,9 @@ public class RealMatrixImpl implements RealMatrix, Serializable {
}
for (int i = 0; i < col; i++) {
final double[] bpI = bp[i];
final double[] luI = lu[i];
final double luICol = lu[i][col];
for (int j = 0; j < nColB; j++) {
bpI[j] -= bp[col][j] * luI[col];
bpI[j] -= bpCol[j] * luICol;
}
}
}

View File

@ -0,0 +1,682 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.linear;
/**
* Interface defining a real-valued vector with basic algebraic operations.
* <p>
* vector element indexing is 0-based -- e.g., <code>getEntry(0)</code>
* returns the first element of the vector.
* </p>
* <p>
* The various <code>mapXxx</code> and <code>mapXxxToSelf</code> methods operate
* on vectors element-wise, i.e. they perform the same operation (adding a scalar,
* applying a function ...) on each element in turn. The <code>mapXxx</code>
* versions create a new vector to hold the result and do not change the instance.
* The <code>mapXxxToSelf</code> versions use the instance itself to store the
* results, so the instance is changed by these methods. In both cases, the result
* vector is returned by the methods, this allows to use the <i>fluent API</i>
* style, like this:
* </p>
* <pre>
* RealVector result = v.mapAddToSelf(3.0).mapTanToSelf().mapSquareToSelf();
* </pre>
*
* @version $Revision$ $Date$
* @since 2.0
*/
public interface RealVector {
/**
* Returns a (deep) copy of this.
* @return vector copy
*/
RealVector copy();
/**
* Compute the sum of this and v.
* @param v vector to be added
* @return this + v
* @throws IllegalArgumentException if v is not the same size as this
*/
RealVector add(RealVector v)
throws IllegalArgumentException;
/**
* Compute this minus v.
* @param v vector to be subtracted
* @return this + v
* @throws IllegalArgumentException if v is not the same size as this
*/
RealVector subtract(RealVector v)
throws IllegalArgumentException;
/**
* Map an addition operation to each entry.
* @param d value to be added to each entry
* @return this + d
*/
RealVector mapAdd(double d);
/**
* Map an addition operation to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @param d value to be added to each entry
* @return for convenience, return this
*/
RealVector mapAddToSelf(double d);
/**
* Map a subtraction operation to each entry.
* @param d value to be subtracted to each entry
* @return this - d
*/
RealVector mapSubtract(double d);
/**
* Map a subtraction operation to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @param d value to be subtracted to each entry
* @return for convenience, return this
*/
RealVector mapSubtractToSelf(double d);
/**
* Map a multiplication operation to each entry.
* @param d value to multiply all entries by
* @return this * d
*/
RealVector mapMultiply(double d);
/**
* Map a multiplication operation to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @param d value to multiply all entries by
* @return for convenience, return this
*/
RealVector mapMultiplyToSelf(double d);
/**
* Map a division operation to each entry.
* @param d value to divide all entries by
* @return this / d
*/
RealVector mapDivide(double d);
/**
* Map a division operation to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @param d value to divide all entries by
* @return for convenience, return this
*/
RealVector mapDivideToSelf(double d);
/**
* Map a power operation to each entry.
* @param d value to raise all entries to
* @return this ^ d
*/
RealVector mapPow(double d);
/**
* Map a power operation to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @param d value to raise all entries to
* @return for convenience, return this
*/
RealVector mapPowToSelf(double d);
/**
* Map the {@link Math#exp(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapExp();
/**
* Map the {@link Math#exp(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapExpToSelf();
/**
* Map the {@link Math#expm1(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapExpm1();
/**
* Map the {@link Math#expm1(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapExpm1ToSelf();
/**
* Map the {@link Math#log(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapLog();
/**
* Map the {@link Math#log(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapLogToSelf();
/**
* Map the {@link Math#log10(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapLog10();
/**
* Map the {@link Math#log10(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapLog10ToSelf();
/**
* Map the {@link Math#log1p(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapLog1p();
/**
* Map the {@link Math#log1p(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapLog1pToSelf();
/**
* Map the {@link Math#cosh(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapCosh();
/**
* Map the {@link Math#cosh(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapCoshToSelf();
/**
* Map the {@link Math#sinh(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapSinh();
/**
* Map the {@link Math#sinh(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapSinhToSelf();
/**
* Map the {@link Math#tanh(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapTanh();
/**
* Map the {@link Math#tanh(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapTanhToSelf();
/**
* Map the {@link Math#cos(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapCos();
/**
* Map the {@link Math#cos(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapCosToSelf();
/**
* Map the {@link Math#sin(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapSin();
/**
* Map the {@link Math#sin(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapSinToSelf();
/**
* Map the {@link Math#tan(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapTan();
/**
* Map the {@link Math#tan(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapTanToSelf();
/**
* Map the {@link Math#acos(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapAcos();
/**
* Map the {@link Math#acos(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapAcosToSelf();
/**
* Map the {@link Math#asin(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapAsin();
/**
* Map the {@link Math#asin(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapAsinToSelf();
/**
* Map the {@link Math#atan(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapAtan();
/**
* Map the {@link Math#atan(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapAtanToSelf();
/**
* Map the 1/x function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapInv();
/**
* Map the 1/x function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapInvToSelf();
/**
* Map the {@link Math#abs(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapAbs();
/**
* Map the {@link Math#abs(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapAbsToSelf();
/**
* Map the {@link Math#sqrt(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapSqrt();
/**
* Map the {@link Math#sqrt(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapSqrtToSelf();
/**
* Map the {@link Math#cbrt(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapCbrt();
/**
* Map the {@link Math#cbrt(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapCbrtToSelf();
/**
* Map the {@link Math#ceil(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapCeil();
/**
* Map the {@link Math#ceil(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapCeilToSelf();
/**
* Map the {@link Math#floor(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapFloor();
/**
* Map the {@link Math#floor(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapFloorToSelf();
/**
* Map the {@link Math#rint(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapRint();
/**
* Map the {@link Math#rint(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapRintToSelf();
/**
* Map the {@link Math#signum(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapSignum();
/**
* Map the {@link Math#signum(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapSignumToSelf();
/**
* Map the {@link Math#ulp(double)} function to each entry.
* @return a vector containing the result of applying the function to each entry
*/
RealVector mapUlp();
/**
* Map the {@link Math#ulp(double)} function to each entry.
* <p>The instance <strong>is</strong> changed by this method.</p>
* @return for convenience, return this
*/
RealVector mapUlpToSelf();
/**
* Element-by-element multiplication.
* @param v vector by which instance elements must be multiplied
* @return a vector containing this[i] * v[i] for all i
* @throws IllegalArgumentException if v is not the same size as this
*/
public RealVector ebeMultiply(RealVector v)
throws IllegalArgumentException;
/**
* Element-by-element division.
* @param v vector by which instance elements must be divided
* @return a vector containing this[i] / v[i] for all i
* @throws IllegalArgumentException if v is not the same size as this
*/
public RealVector ebeDivide(RealVector v)
throws IllegalArgumentException;
/**
* Returns vector entries as a double array.
* @return double array of entries
*/
double[] getData();
/**
* Compute the dot product.
* @param v vector with which dot product should be computed
* @return the scalar dot product between instance and v
* @exception IllegalArgumentException if v is not the same size as this
*/
double dotProduct(RealVector v)
throws IllegalArgumentException;
/**
* Returns the L<sub>2</sub> norm of the vector.
* <p>The L<sub>2</sub> norm is the root of the sum of
* the squared elements.</p>
* @return norm
* @see #getL1Norm()
* @see #getLInfNorm()
* @see #getDistance(RealVector)
*/
double getNorm();
/**
* Returns the L<sub>1</sub> norm of the vector.
* <p>The L<sub>1</sub> norm is the sum of the absolute
* values of elements.</p>
* @return norm
* @see #getNorm()
* @see #getLInfNorm()
* @see #getL1Distance(RealVector)
*/
double getL1Norm();
/**
* Returns the L<sub>&infty;</sub> norm of the vector.
* <p>The L<sub>&infty;</sub> norm is the max of the absolute
* values of elements.</p>
* @return norm
* @see #getNorm()
* @see #getL1Norm()
* @see #getLInfDistance(RealVector)
*/
double getLInfNorm();
/**
* Distance between two vectors.
* <p>This method computes the distance consistent with the
* L<sub>2</sub> norm, i.e. the square root of the sum of
* elements differences, or euclidian distance.</p>
* @param v vector to which distance is requested
* @return distance between two vectors.
* @exception IllegalArgumentException if v is not the same size as this
* @see #getL1Distance(RealVector)
* @see #getLInfDistance(RealVector)
* @see #getNorm()
*/
double getDistance(RealVector v)
throws IllegalArgumentException;
/**
* Distance between two vectors.
* <p>This method computes the distance consistent with
* L<sub>1</sub> norm, i.e. the sum of the absolute values of
* elements differences.</p>
* @param v vector to which distance is requested
* @return distance between two vectors.
* @exception IllegalArgumentException if v is not the same size as this
* @see #getDistance(RealVector)
* @see #getLInfDistance(RealVector)
* @see #getL1Norm()
*/
double getL1Distance(RealVector v)
throws IllegalArgumentException;
/**
* Distance between two vectors.
* <p>This method computes the distance consistent with
* L<sub>&infty;</sub> norm, i.e. the max of the absolute values of
* elements differences.</p>
* @param v vector to which distance is requested
* @return distance between two vectors.
* @exception IllegalArgumentException if v is not the same size as this
* @see #getDistance(RealVector)
* @see #getL1Distance(RealVector)
* @see #getLInfNorm()
*/
double getLInfDistance(RealVector v)
throws IllegalArgumentException;
/** Creates a unit vector pointing in the direction of this vector.
* <p>The instance is not changed by this method.</p>
* @return a unit vector pointing in direction of this vector
* @exception ArithmeticException if the norm is null
*/
RealVector unitVector();
/** Converts this vector into a unit vector.
* <p>The instance itself is changed by this method.</p>
* @exception ArithmeticException if the norm is null
*/
void unitize();
/** Find the orthogonal projection of this vector onto another vector.
* @param v vector onto which instance must be projected
* @return projection of the instance onto v
* @throws IllegalArgumentException if v is not the same size as this
*/
RealVector projection(RealVector v)
throws IllegalArgumentException;
/**
* Compute the outer product.
* @param v vector with which outer product should be computed
* @return the square matrix outer product between instance and v
* @exception IllegalArgumentException if v is not the same size as this
*/
RealMatrix outerProduct(RealVector v)
throws IllegalArgumentException;
/**
* Returns the entry in the specified index.
* <p>
* The index start at 0 and must be lesser than the size,
* otherwise a {@link MatrixIndexException} is thrown.
* </p>
* @param index index location of entry to be fetched
* @return vector entry at index
* @throws MatrixIndexException if the index is not valid
*/
double getEntry(int index)
throws MatrixIndexException;
/**
* Returns the size of the vector.
* @return size
*/
int getDimension();
/**
* Construct a vector by appending a vector to this vector.
* @param v vector to append to this one.
* @return a new vector
*/
RealVector append(RealVector v);
/**
* Construct a vector by appending a double to this vector.
* @param d double to append.
* @return a new vector
*/
RealVector append(double d);
/**
* Construct a vector by appending a double array to this vector.
* @param a double array to append.
* @return a new vector
*/
RealVector append(double[] a);
/**
* Get a subvector from consecutive elements.
* @param index index of first element.
* @param n number of elements to be retrieved.
* @return a vector containing n elements.
* @exception MatrixIndexException if the index is
* inconsistent with vector size
*/
RealVector get(int index, int n)
throws MatrixIndexException;
/**
* Set a single element.
* @param index element index.
* @param value new value for the element.
* @exception MatrixIndexException if the index is
* inconsistent with vector size
*/
void set(int index, double value)
throws MatrixIndexException;
/**
* Set a set of consecutive elements.
* @param index index of first element to be set.
* @param v vector containing the values to set.
* @exception MatrixIndexException if the index is
* inconsistent with vector size
*/
void set(int index, RealVector v)
throws MatrixIndexException;
/**
* Set all elements to a single value.
* @param value single value to set for all elements
*/
void set(double value);
/**
* Convert the vector to a double array.
* <p>The array is independent from vector data, it's elements
* are copied.</p>
* @return array containing a copy of vector elements
*/
double[] toArray();
/**
* Returns true if any coordinate of this vector is NaN; false otherwise
* @return true if any coordinate of this vector is NaN; false otherwise
*/
public boolean isNaN();
/**
* Returns true if any coordinate of this vector is infinite and none are NaN;
* false otherwise
* @return true if any coordinate of this vector is infinite and none are NaN;
* false otherwise
*/
public boolean isInfinite();
}

View File

@ -0,0 +1,334 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.linear;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.apache.commons.math.util.CompositeFormat;
/**
* Formats a vector in components list format "{v0; v1; ...; vk-1}".
* <p>The prefix and suffix "{" and "}" and the separator "; " can be replaced by
* any user-defined strings. The number format for components can be configured.</p>
* <p>White space is ignored at parse time, even if it is in the prefix, suffix
* or separator specifications. So even if the default separator does include a space
* character that is used at format time, both input string "{1;1;1}" and
* " { 1 ; 1 ; 1 } " will be parsed without error and the same vector will be
* returned. In the second case, however, the parse position after parsing will be
* just after the closing curly brace, i.e. just before the trailing space.</p>
*
* @version $Revision$ $Date$
* @since 2.0
*/
public class RealVectorFormat extends CompositeFormat {
/** Serializable version identifier */
private static final long serialVersionUID = -708767813036157690L;
/** The default prefix: "{". */
private static final String DEFAULT_PREFIX = "{";
/** The default suffix: "}". */
private static final String DEFAULT_SUFFIX = "}";
/** The default separator: ", ". */
private static final String DEFAULT_SEPARATOR = "; ";
/** Prefix. */
private final String prefix;
/** Suffix. */
private final String suffix;
/** Separator. */
private final String separator;
/** Trimmed prefix. */
private final String trimmedPrefix;
/** Trimmed suffix. */
private final String trimmedSuffix;
/** Trimmed separator. */
private final String trimmedSeparator;
/** The format used for components. */
private NumberFormat format;
/**
* Create an instance with default settings.
* <p>The instance uses the default prefix, suffix and separator:
* "{", "}", and "; " and the default number format for components.</p>
*/
public RealVectorFormat() {
this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, getDefaultNumberFormat());
}
/**
* Create an instance with a custom number format for components.
* @param format the custom format for components.
*/
public RealVectorFormat(final NumberFormat format) {
this(DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_SEPARATOR, format);
}
/**
* Create an instance with custom prefix, suffix and separator.
* @param prefix prefix to use instead of the default "{"
* @param suffix suffix to use instead of the default "}"
* @param separator separator to use instead of the default "; "
*/
public RealVectorFormat(final String prefix, final String suffix,
final String separator) {
this(prefix, suffix, separator, getDefaultNumberFormat());
}
/**
* Create an instance with custom prefix, suffix, separator and format
* for components.
* @param prefix prefix to use instead of the default "{"
* @param suffix suffix to use instead of the default "}"
* @param separator separator to use instead of the default "; "
* @param format the custom format for components.
*/
public RealVectorFormat(final String prefix, final String suffix,
final String separator, final NumberFormat format) {
this.prefix = prefix;
this.suffix = suffix;
this.separator = separator;
trimmedPrefix = prefix.trim();
trimmedSuffix = suffix.trim();
trimmedSeparator = separator.trim();
this.format = format;
}
/**
* Get the set of locales for which real vectors formats are available.
* <p>This is the same set as the {@link NumberFormat} set.</p>
* @return available real vector format locales.
*/
public static Locale[] getAvailableLocales() {
return NumberFormat.getAvailableLocales();
}
/**
* Get the format prefix.
* @return format prefix.
*/
public String getPrefix() {
return prefix;
}
/**
* Get the format suffix.
* @return format suffix.
*/
public String getSuffix() {
return suffix;
}
/**
* Get the format separator between components.
* @return format separator.
*/
public String getSeparator() {
return separator;
}
/**
* Get the components format.
* @return components format.
*/
public NumberFormat getFormat() {
return format;
}
/**
* Returns the default real vector format for the current locale.
* @return the default real vector format.
*/
public static RealVectorFormat getInstance() {
return getInstance(Locale.getDefault());
}
/**
* Returns the default real vector format for the given locale.
* @param locale the specific locale used by the format.
* @return the real vector format specific to the given locale.
*/
public static RealVectorFormat getInstance(final Locale locale) {
return new RealVectorFormat(getDefaultNumberFormat(locale));
}
/**
* This static method calls {@link #format(Object)} on a default instance of
* RealVectorFormat.
*
* @param v RealVector object to format
* @return A formatted vector
*/
public static String formatRealVector(RealVector v) {
return getInstance().format(v);
}
/**
* Formats a {@link RealVector} object to produce a string.
* @param vector the object to format.
* @param toAppendTo where the text is to be appended
* @param pos On input: an alignment field, if desired. On output: the
* offsets of the alignment field
* @return the value passed in as toAppendTo.
*/
public StringBuffer format(RealVector vector, StringBuffer toAppendTo,
FieldPosition pos) {
pos.setBeginIndex(0);
pos.setEndIndex(0);
// format prefix
toAppendTo.append(prefix);
// format components
for (int i = 0; i < vector.getDimension(); ++i) {
if (i > 0) {
toAppendTo.append(separator);
}
formatDouble(vector.getEntry(i), format, toAppendTo, pos);
}
// format suffix
toAppendTo.append(suffix);
return toAppendTo;
}
/**
* Formats a object to produce a string.
* <p><code>obj</code> must be a {@link RealVector} object. Any other type of
* object will result in an {@link IllegalArgumentException} being thrown.</p>
* @param obj the object to format.
* @param toAppendTo where the text is to be appended
* @param pos On input: an alignment field, if desired. On output: the
* offsets of the alignment field
* @return the value passed in as toAppendTo.
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
* @throws IllegalArgumentException is <code>obj</code> is not a valid type.
*/
public StringBuffer format(Object obj, StringBuffer toAppendTo,
FieldPosition pos) {
if (obj instanceof RealVector) {
return format( (RealVector)obj, toAppendTo, pos);
}
throw new IllegalArgumentException("Cannot format given Object as a RealVector");
}
/**
* Parses a string to produce a {@link RealVector} object.
* @param source the string to parse
* @return the parsed {@link RealVector} object.
* @exception ParseException if the beginning of the specified string
* cannot be parsed.
*/
public RealVectorImpl parse(String source) throws ParseException {
ParsePosition parsePosition = new ParsePosition(0);
RealVectorImpl result = parse(source, parsePosition);
if (parsePosition.getIndex() == 0) {
throw new ParseException("Unparseable real vector: \"" + source +
"\"", parsePosition.getErrorIndex());
}
return result;
}
/**
* Parses a string to produce a {@link RealVector} object.
* @param source the string to parse
* @param pos input/ouput parsing parameter.
* @return the parsed {@link RealVector} object.
*/
public RealVectorImpl parse(String source, ParsePosition pos) {
int initialIndex = pos.getIndex();
// parse prefix
parseAndIgnoreWhitespace(source, pos);
if (!parseFixedstring(source, trimmedPrefix, pos)) {
return null;
}
// parse components
List<Number> components = new ArrayList<Number>();
for (boolean loop = true; loop;){
if (!components.isEmpty()) {
parseAndIgnoreWhitespace(source, pos);
if (!parseFixedstring(source, trimmedSeparator, pos)) {
loop = false;
}
}
if (loop) {
parseAndIgnoreWhitespace(source, pos);
Number component = parseNumber(source, format, pos);
if (component != null) {
components.add(component);
} else {
// invalid component
// set index back to initial, error index should already be set
pos.setIndex(initialIndex);
return null;
}
}
}
// parse suffix
parseAndIgnoreWhitespace(source, pos);
if (!parseFixedstring(source, trimmedSuffix, pos)) {
return null;
}
// build vector
double[] data = new double[components.size()];
for (int i = 0; i < data.length; ++i) {
data[i] = components.get(i).doubleValue();
}
return new RealVectorImpl(data, false);
}
/**
* Parses a string to produce a object.
* @param source the string to parse
* @param pos input/ouput parsing parameter.
* @return the parsed object.
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
*/
public Object parseObject(String source, ParsePosition pos) {
return parse(source, pos);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,12 @@ The <action> type attribute can be add,update,fix,remove.
</properties>
<body>
<release version="2.0" date="TBD" description="TBD">
<action dev="luc" type="add" due-to="Andreas Rieger">
Support for one dimensional vectors has been added to the linear algebra
package with a RealVector interface, a RealVectorImpl default implementation
using a single double array to store elements and a RealVectorFormat for
input/output.
</action>
<action dev="psteitz" type="update" issue="MATH-217">
Changed OLS regression implementation added in MATH-203 to use
QR decomposition to solve the normal equations.

View File

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.linear;
import java.util.Locale;
public class FrenchRealVectorFormatTest extends RealVectorFormatAbstractTest {
protected char getDecimalCharacter() {
return ',';
}
protected Locale getLocale() {
return Locale.FRENCH;
}
}

View File

@ -253,8 +253,10 @@ public final class RealMatrixImplTest extends TestCase {
RealMatrixImpl m = new RealMatrixImpl(testData);
RealMatrix mInv = new RealMatrixImpl(testDataInv);
// being a bit slothful here -- actually testing that X = A^-1 * B
assertClose("inverse-operate",mInv.operate(testVector),
m.solve(testVector),normTolerance);
assertClose("inverse-operate", mInv.operate(testVector),
m.solve(testVector), normTolerance);
assertClose("inverse-operate", mInv.operate(testVector),
m.solve(new RealVectorImpl(testVector)).getData(), normTolerance);
try {
m.solve(testVector2);
fail("expecting IllegalArgumentException");
@ -332,8 +334,10 @@ public final class RealMatrixImplTest extends TestCase {
/** test operate */
public void testOperate() {
RealMatrix m = new RealMatrixImpl(id);
double[] x = m.operate(testVector);
assertClose("identity operate",testVector,x,entryTolerance);
assertClose("identity operate", testVector,
m.operate(testVector), entryTolerance);
assertClose("identity operate", testVector,
m.operate(new RealVectorImpl(testVector)).getData(), entryTolerance);
m = new RealMatrixImpl(bigSingular);
try {
m.operate(testVector);
@ -368,7 +372,10 @@ public final class RealMatrixImplTest extends TestCase {
/** test preMultiply by vector */
public void testPremultiplyVector() {
RealMatrix m = new RealMatrixImpl(testData);
assertClose("premultiply",m.preMultiply(testVector),preMultTest,normTolerance);
assertClose("premultiply", m.preMultiply(testVector),
preMultTest, normTolerance);
assertClose("premultiply", m.preMultiply(new RealVectorImpl(testVector).getData()),
preMultTest, normTolerance);
m = new RealMatrixImpl(bigSingular);
try {
m.preMultiply(testVector);
@ -607,6 +614,54 @@ public final class RealMatrixImplTest extends TestCase {
// expected
}
}
public void testGetRowVector() {
RealMatrix m = new RealMatrixImpl(subTestData);
RealVector mRow0 = new RealVectorImpl(subRow0[0]);
RealVector mRow3 = new RealVectorImpl(subRow3[0]);
assertEquals("Row0", mRow0, m.getRowVector(0));
assertEquals("Row3", mRow3, m.getRowVector(3));
try {
m.getRowVector(-1);
fail("Expecting MatrixIndexException");
} catch (MatrixIndexException ex) {
// expected
}
try {
m.getRowVector(4);
fail("Expecting MatrixIndexException");
} catch (MatrixIndexException ex) {
// expected
}
}
public void testGetColumnVector() {
RealMatrix m = new RealMatrixImpl(subTestData);
RealVector mColumn1 = columnToVector(subColumn1);
RealVector mColumn3 = columnToVector(subColumn3);
assertEquals("Column1", mColumn1, m.getColumnVector(1));
assertEquals("Column3", mColumn3, m.getColumnVector(3));
try {
m.getColumnVector(-1);
fail("Expecting MatrixIndexException");
} catch (MatrixIndexException ex) {
// expected
}
try {
m.getColumnVector(4);
fail("Expecting MatrixIndexException");
} catch (MatrixIndexException ex) {
// expected
}
}
private RealVector columnToVector(double[][] column) {
double[] data = new double[column.length];
for (int i = 0; i < data.length; ++i) {
data[i] = column[i][0];
}
return new RealVectorImpl(data, false);
}
public void testEqualsAndHashCode() {
RealMatrixImpl m = new RealMatrixImpl(testData);

View File

@ -0,0 +1,384 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.linear;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;
import junit.framework.TestCase;
import org.apache.commons.math.util.CompositeFormat;
public abstract class RealVectorFormatAbstractTest extends TestCase {
RealVectorFormat realVectorFormat = null;
RealVectorFormat realVectorFormatSquare = null;
protected abstract Locale getLocale();
protected abstract char getDecimalCharacter();
protected void setUp() throws Exception {
realVectorFormat = RealVectorFormat.getInstance(getLocale());
final NumberFormat nf = NumberFormat.getInstance(getLocale());
nf.setMaximumFractionDigits(2);
realVectorFormatSquare = new RealVectorFormat("[", "]", " : ", nf);
}
public void testSimpleNoDecimals() {
RealVectorImpl c = new RealVectorImpl(new double[] {1, 1, 1});
String expected = "{1; 1; 1}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testSimpleWithDecimals() {
RealVectorImpl c = new RealVectorImpl(new double[] {1.23, 1.43, 1.63});
String expected =
"{1" + getDecimalCharacter() +
"23; 1" + getDecimalCharacter() +
"43; 1" + getDecimalCharacter() +
"63}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testSimpleWithDecimalsTrunc() {
RealVectorImpl c = new RealVectorImpl(new double[] {1.2323, 1.4343, 1.6333});
String expected =
"{1" + getDecimalCharacter() +
"23; 1" + getDecimalCharacter() +
"43; 1" + getDecimalCharacter() +
"63}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testNegativeX() {
RealVectorImpl c = new RealVectorImpl(new double[] {-1.2323, 1.4343, 1.6333});
String expected =
"{-1" + getDecimalCharacter() +
"23; 1" + getDecimalCharacter() +
"43; 1" + getDecimalCharacter() +
"63}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testNegativeY() {
RealVectorImpl c = new RealVectorImpl(new double[] {1.2323, -1.4343, 1.6333});
String expected =
"{1" + getDecimalCharacter() +
"23; -1" + getDecimalCharacter() +
"43; 1" + getDecimalCharacter() +
"63}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testNegativeZ() {
RealVectorImpl c = new RealVectorImpl(new double[] {1.2323, 1.4343, -1.6333});
String expected =
"{1" + getDecimalCharacter() +
"23; 1" + getDecimalCharacter() +
"43; -1" + getDecimalCharacter() +
"63}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testNonDefaultSetting() {
RealVectorImpl c = new RealVectorImpl(new double[] {1, 1, 1});
String expected = "[1 : 1 : 1]";
String actual = realVectorFormatSquare.format(c);
assertEquals(expected, actual);
}
public void testStaticFormatRealVectorImpl() {
Locale defaultLocal = Locale.getDefault();
Locale.setDefault(getLocale());
RealVectorImpl c = new RealVectorImpl(new double[] {232.222, -342.33, 432.444});
String expected =
"{232" + getDecimalCharacter() +
"22; -342" + getDecimalCharacter() +
"33; 432" + getDecimalCharacter() +
"44}";
String actual = RealVectorFormat.formatRealVector(c);
assertEquals(expected, actual);
Locale.setDefault(defaultLocal);
}
public void testNan() {
RealVectorImpl c = new RealVectorImpl(new double[] {Double.NaN, Double.NaN, Double.NaN});
String expected = "{(NaN); (NaN); (NaN)}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testPositiveInfinity() {
RealVectorImpl c = new RealVectorImpl(new double[] {
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY
});
String expected = "{(Infinity); (Infinity); (Infinity)}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void tesNegativeInfinity() {
RealVectorImpl c = new RealVectorImpl(new double[] {
Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY
});
String expected = "{(-Infinity); (-Infinity); (-Infinity)}";
String actual = realVectorFormat.format(c);
assertEquals(expected, actual);
}
public void testParseSimpleNoDecimals() {
String source = "{1; 1; 1}";
RealVectorImpl expected = new RealVectorImpl(new double[] {1, 1, 1});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseIgnoredWhitespace() {
RealVectorImpl expected = new RealVectorImpl(new double[] {1, 1, 1});
ParsePosition pos1 = new ParsePosition(0);
String source1 = "{1;1;1}";
assertEquals(expected, realVectorFormat.parseObject(source1, pos1));
assertEquals(source1.length(), pos1.getIndex());
ParsePosition pos2 = new ParsePosition(0);
String source2 = " { 1 ; 1 ; 1 } ";
assertEquals(expected, realVectorFormat.parseObject(source2, pos2));
assertEquals(source2.length() - 1, pos2.getIndex());
}
public void testParseSimpleWithDecimals() {
String source =
"{1" + getDecimalCharacter() +
"23; 1" + getDecimalCharacter() +
"43; 1" + getDecimalCharacter() +
"63}";
RealVectorImpl expected = new RealVectorImpl(new double[] {1.23, 1.43, 1.63});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseSimpleWithDecimalsTrunc() {
String source =
"{1" + getDecimalCharacter() +
"2323; 1" + getDecimalCharacter() +
"4343; 1" + getDecimalCharacter() +
"6333}";
RealVectorImpl expected = new RealVectorImpl(new double[] {1.2323, 1.4343, 1.6333});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNegativeX() {
String source =
"{-1" + getDecimalCharacter() +
"2323; 1" + getDecimalCharacter() +
"4343; 1" + getDecimalCharacter() +
"6333}";
RealVectorImpl expected = new RealVectorImpl(new double[] {-1.2323, 1.4343, 1.6333});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNegativeY() {
String source =
"{1" + getDecimalCharacter() +
"2323; -1" + getDecimalCharacter() +
"4343; 1" + getDecimalCharacter() +
"6333}";
RealVectorImpl expected = new RealVectorImpl(new double[] {1.2323, -1.4343, 1.6333});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNegativeZ() {
String source =
"{1" + getDecimalCharacter() +
"2323; 1" + getDecimalCharacter() +
"4343; -1" + getDecimalCharacter() +
"6333}";
RealVectorImpl expected = new RealVectorImpl(new double[] {1.2323, 1.4343, -1.6333});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNegativeAll() {
String source =
"{-1" + getDecimalCharacter() +
"2323; -1" + getDecimalCharacter() +
"4343; -1" + getDecimalCharacter() +
"6333}";
RealVectorImpl expected = new RealVectorImpl(new double[] {-1.2323, -1.4343, -1.6333});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseZeroX() {
String source =
"{0" + getDecimalCharacter() +
"0; -1" + getDecimalCharacter() +
"4343; 1" + getDecimalCharacter() +
"6333}";
RealVectorImpl expected = new RealVectorImpl(new double[] {0.0, -1.4343, 1.6333});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNonDefaultSetting() {
String source =
"[1" + getDecimalCharacter() +
"2323 : 1" + getDecimalCharacter() +
"4343 : 1" + getDecimalCharacter() +
"6333]";
RealVectorImpl expected = new RealVectorImpl(new double[] {1.2323, 1.4343, 1.6333});
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormatSquare.parseObject(source);
assertEquals(expected, actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNan() {
String source = "{(NaN); (NaN); (NaN)}";
try {
RealVectorImpl actual = (RealVectorImpl) realVectorFormat.parseObject(source);
assertEquals(new RealVectorImpl(new double[] {Double.NaN, Double.NaN, Double.NaN}), actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParsePositiveInfinity() {
String source = "{(Infinity); (Infinity); (Infinity)}";
try {
RealVectorImpl actual = (RealVectorImpl)realVectorFormat.parseObject(source);
assertEquals(new RealVectorImpl(new double[] {
Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY
}), actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNegativeInfinity() {
String source = "{(-Infinity); (-Infinity); (-Infinity)}";
try {
RealVectorImpl actual = (RealVectorImpl)realVectorFormat.parseObject(source);
assertEquals(new RealVectorImpl(new double[] {
Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY
}), actual);
} catch (ParseException ex) {
fail(ex.getMessage());
}
}
public void testParseNoComponents() {
try {
realVectorFormat.parseObject("{ }");
} catch (ParseException pe) {
// expected behavior
} catch (Exception e) {
fail("wrong exception caught");
}
}
public void testParseManyComponents() throws ParseException {
RealVectorImpl parsed =
(RealVectorImpl) realVectorFormat.parseObject("{0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0}");
assertEquals(24, parsed.getDimension());
}
public void testConstructorSingleFormat() {
NumberFormat nf = NumberFormat.getInstance();
RealVectorFormat cf = new RealVectorFormat(nf);
assertNotNull(cf);
assertEquals(nf, cf.getFormat());
}
public void testFormatObject() {
try {
CompositeFormat cf = new RealVectorFormat();
Object object = new Object();
cf.format(object);
fail();
} catch (IllegalArgumentException ex) {
// success
}
}
public void testForgottenPrefix() {
ParsePosition pos = new ParsePosition(0);
assertNull(new RealVectorFormat().parse("1; 1; 1}", pos));
assertEquals(0, pos.getErrorIndex());
}
public void testForgottenSeparator() {
ParsePosition pos = new ParsePosition(0);
assertNull(new RealVectorFormat().parse("{1; 1 1}", pos));
assertEquals(6, pos.getErrorIndex());
}
public void testForgottenSuffix() {
ParsePosition pos = new ParsePosition(0);
assertNull(new RealVectorFormat().parse("{1; 1; 1 ", pos));
assertEquals(8, pos.getErrorIndex());
}
}

View File

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.linear;
import java.util.Locale;
public class RealVectorFormatTest extends RealVectorFormatAbstractTest {
protected char getDecimalCharacter() {
return '.';
}
protected Locale getLocale() {
return Locale.US;
}
}

File diff suppressed because it is too large Load Diff