Author: desruisseaux
Date: Thu Oct 3 10:35:05 2013
New Revision: 1528793
URL: http://svn.apache.org/r1528793
Log:
Add convenience method in DoubleDouble working on array.
This make the code more readable in GeneralMatrix and Solver.
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java?rev=1528793&r1=1528792&r2=1528793&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] Thu Oct 3 10:35:05 2013
@@ -140,6 +140,20 @@ class GeneralMatrix extends MatrixSIS {
}
/**
+ * Creates a new extended precision matrix of the given size.
+ *
+ * @param numRow Number of rows.
+ * @param numCol Number of columns.
+ */
+ static GeneralMatrix createExtendedPrecision(final int numRow, final int
numCol) {
+ if (numRow == numCol) {
+ return new GeneralMatrix(numRow, numCol, false, 2);
+ } else {
+ return new NonSquareMatrix(numRow, numCol, false, 2);
+ }
+ }
+
+ /**
* Copies the elements of the given matrix in the given array.
* This method ignores the error terms, if any.
*
@@ -415,9 +429,9 @@ class GeneralMatrix extends MatrixSIS {
*/
final double[] eltA = getExtendedElements(A, numRow, nc);
final double[] eltB = getExtendedElements(B, nc, numCol);
- final int errors = numRow * numCol; // Where error values start,
or 0 if none.
- final int errA = numRow * nc;
- final int errB = nc * numCol;
+ final int errorOffset = numRow * numCol; // Where error terms start.
+ final int errA = numRow * nc;
+ final int errB = nc * numCol;
/*
* Compute the product, to be stored directly in 'this'.
*/
@@ -430,15 +444,13 @@ class GeneralMatrix extends MatrixSIS {
int iA = j * nc; // Index of values in a single row of A.
final int nextRow = iA + nc;
while (iA < nextRow) {
- dot.value = eltA[iA];
- dot.error = eltA[iA + errA];
- dot.multiply(eltB[iB], eltB[iB + errB]);
+ dot.setFrom (eltA, iA, errA);
+ dot.multiply(eltB, iB, errB);
sum.add(dot);
iB += numCol; // Move to next row of B.
iA++; // Move to next column of A.
}
- elements[k + errors] = sum.error;
- elements[k++] = sum.value;
+ sum.storeTo(elements, k++, errorOffset);
}
}
}
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java?rev=1528793&r1=1528792&r2=1528793&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
(original)
+++
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
Thu Oct 3 10:35:05 2013
@@ -209,12 +209,7 @@ public abstract class MatrixSIS implemen
final int numCol = getNumCol();
final int nc = matrix.getNumCol();
ensureNumRowMatch(numCol, matrix, nc);
- final GeneralMatrix result;
- if (numRow == nc) {
- result = new GeneralMatrix(numRow, nc, false, 2);
- } else {
- result = new NonSquareMatrix(numRow, nc, false, 2);
- }
+ final GeneralMatrix result =
GeneralMatrix.createExtendedPrecision(numRow, nc);
result.setToProduct(this, matrix);
return result;
}
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java?rev=1528793&r1=1528792&r2=1528793&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java
[UTF-8] Thu Oct 3 10:35:05 2013
@@ -140,8 +140,8 @@ final class Solver implements Matrix {
for (int j=0; j<size; j++) {
pivot[j] = j;
}
- final double[] column = new double[size * 2];
- final DoubleDouble dot = new DoubleDouble();
+ final double[] column = new double[size * 2]; // [0 … size-1] :
column values; [size … 2*size-1] : error terms.
+ final DoubleDouble tmp = new DoubleDouble();
final DoubleDouble sum = new DoubleDouble();
for (int i=0; i<size; i++) {
/*
@@ -149,8 +149,8 @@ final class Solver implements Matrix {
*/
for (int j=0; j<size; j++) {
final int k = j*size + i;
- column[j] = LU[k];
- column[j + size] = LU[k + errorLU];
+ column[j] = LU[k]; // Value
+ column[j + size] = LU[k + errorLU]; // Error
}
/*
* Apply previous transformations.
@@ -160,14 +160,14 @@ final class Solver implements Matrix {
final int kmax = Math.min(j,i);
sum.clear();
for (int k=0; k<kmax; k++) {
- dot.value = LU[rowOffset + k];
- dot.error = LU[rowOffset + k + errorLU];
- dot.multiply(column[k], column[k + size]);
- sum.add(dot);
- }
- sum.add(-column[j], -column[j + size]);
- LU[rowOffset + i] = column[j] = -sum.value;
- LU[rowOffset + i + errorLU] = column[j + size] = -sum.error;
+ tmp.setFrom(LU, rowOffset + k, errorLU);
+ tmp.multiply(column, k, size);
+ sum.add(tmp);
+ }
+ sum.subtract(column, j, size);
+ sum.negate();
+ sum.storeTo(column, j, size);
+ sum.storeTo(LU, rowOffset + i, errorLU);
}
/*
* Find pivot and exchange if necessary.
@@ -182,17 +182,20 @@ final class Solver implements Matrix {
final int pRow = p*size;
final int iRow = i*size;
for (int k=0; k<size; k++) { // Swap two full rows.
- ArraysExt.swap(LU, pRow + k, iRow + k);
+ DoubleDouble.swap(LU, pRow + k, iRow + k, errorLU);
}
ArraysExt.swap(pivot, p, i);
}
/*
* Compute multipliers.
*/
- final double d = LU[i*size + i];
- if (d != 0.0) {
+ sum.setFrom(LU, i*size + i, errorLU);
+ if (!sum.isZero()) {
for (int j=i; ++j < size;) {
- LU[j*size + i] /= d;
+ final int t = j*size + i;
+ tmp.setFrom(LU, t, errorLU);
+ tmp.divide(sum);
+ tmp.storeTo(LU, t, errorLU);
}
}
}
@@ -201,7 +204,8 @@ final class Solver implements Matrix {
* Ensure that the matrix is not singular.
*/
for (int j=0; j<size; j++) {
- if (LU[j*size + j] == 0) {
+ tmp.setFrom(LU, j*size + j, errorLU);
+ if (tmp.isZero()) {
throw new NoninvertibleMatrixException();
}
}
@@ -209,7 +213,8 @@ final class Solver implements Matrix {
* Copy right hand side with pivoting.
* We will write the result of this method directly in the elements
array.
*/
- final double[] elements = new double[size * innerSize];
+ final GeneralMatrix result =
GeneralMatrix.createExtendedPrecision(size, innerSize);
+ final double[] elements = result.elements;
for (int k=0,j=0; j<size; j++) {
final int p = pivot[j];
for (int i=0; i<innerSize; i++) {
@@ -223,7 +228,7 @@ final class Solver implements Matrix {
final int rowOffset = k*innerSize; // Offset of row
computed by current iteration.
for (int j=k; ++j < size;) {
final int loRowOffset = j*innerSize; // Offset of a row
after (locate lower) the current row.
- final int luRowOffset = j*size; // Offset of the
corresponding row in the LU matrix.
+ final int luRowOffset = j*size; // Offset of the
corresponding row in the LU matrix.
for (int i=0; i<innerSize; i++) {
elements[loRowOffset + i] -= (elements[rowOffset + i] *
LU[luRowOffset + k]);
}
@@ -246,6 +251,6 @@ final class Solver implements Matrix {
}
}
}
- return Matrices.create(size, innerSize, elements);
+ return result;
}
}
Modified:
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java?rev=1528793&r1=1528792&r2=1528793&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
[UTF-8] Thu Oct 3 10:35:05 2013
@@ -224,6 +224,15 @@ public final class DoubleDouble extends
}
/**
+ * Returns {@code true} if this {@code DoubleDouble} is equals to zero.
+ *
+ * @return {@code true} if this {@code DoubleDouble} is equals to zero.
+ */
+ public boolean isZero() {
+ return value == 0 && error == 0;
+ }
+
+ /**
* Resets the {@link #value} and {@link #error} terms to zero.
*/
public void clear() {
@@ -232,6 +241,24 @@ public final class DoubleDouble extends
}
/**
+ * Sets the {@link #value} and {@link #error} terms to values read from
the given array.
+ * This is a convenience method for a frequently used operation,
implemented as below:
+ *
+ * {@preformat java
+ * value = array[index];
+ * error = array[index + errorOffset];
+ * }
+ *
+ * @param array The array from which to get the value and error.
+ * @param index Index of the value in the given array.
+ * @param errorOffset Offset to add to {@code index} in order to get the
index of the error in the given array.
+ */
+ public void setFrom(final double[] array, final int index, final int
errorOffset) {
+ value = array[index];
+ error = array[index + errorOffset];
+ }
+
+ /**
* Equivalent to a call to {@code setToQuickSum(value, error)} inlined.
* This is invoked after addition or multiplication operations.
*/
@@ -292,6 +319,51 @@ public final class DoubleDouble extends
}
/**
+ * Stores the {@link #value} and {@link #error} terms in the given array.
+ * This is a convenience method for a frequently used operation,
implemented as below:
+ *
+ * {@preformat java
+ * array[index] = value;
+ * array[index + errorOffset] = error;
+ * }
+ *
+ * @param array The array where to store the value and error.
+ * @param index Index of the value in the given array.
+ * @param errorOffset Offset to add to {@code index} in order to get the
index of the error in the given array.
+ */
+ public void storeTo(final double[] array, final int index, final int
errorOffset) {
+ array[index] = value;
+ array[index + errorOffset] = error;
+ }
+
+ /**
+ * Swaps two double-double values in the given array.
+ *
+ * @param array The array where to swap the values and errors.
+ * @param i0 Index of the first value to swap.
+ * @param i1 Index of the second value to swap.
+ * @param errorOffset Offset to add to the indices in order to get the
error indices in the given array.
+ *
+ * @see org.apache.sis.util.ArraysExt#swap(double[], int, int)
+ */
+ public static void swap(final double[] array, int i0, int i1, final int
errorOffset) {
+ double t = array[i0];
+ array[i0] = array[i1];
+ array[i1] = t;
+ t = array[i0 += errorOffset];
+ array[i0] = array[i1 += errorOffset];
+ array[i1] = t;
+ }
+
+ /**
+ * Set this number to {@code -this}.
+ */
+ public void negate() {
+ value = -value;
+ error = -error;
+ }
+
+ /**
* Adds an other double-double value to this {@code DoubleDouble}.
* This is a convenience method for:
*
@@ -343,6 +415,63 @@ public final class DoubleDouble extends
}
/**
+ * Adds an other double-double value to this {@code DoubleDouble}, reading
the values from an array.
+ * This is a convenience method for a frequently used operation,
implemented as below:
+ *
+ * {@preformat java
+ * add(array[index], array[index + errorOffset]);
+ * }
+ *
+ * @param array The array from which to get the value and error.
+ * @param index Index of the value in the given array.
+ * @param errorOffset Offset to add to {@code index} in order to get the
index of the error in the given array.
+ */
+ public void add(final double[] array, final int index, final int
errorOffset) {
+ add(array[index], array[index + errorOffset]);
+ }
+
+ /**
+ * Subtracts an other double-double value from this {@code DoubleDouble}.
+ * This is a convenience method for:
+ *
+ * {@preformat java
+ * subtract(other.value, other.error);
+ * }
+ *
+ * @param other The other value to subtract from this value.
+ */
+ public void subtract(final DoubleDouble other) {
+ subtract(other.value, other.error);
+ }
+
+ /**
+ * Subtracts an other double-double value from this {@code DoubleDouble}.
+ * The result is stored in this instance.
+ *
+ * @param otherValue The other value to subtract from this {@code
DoubleDouble}.
+ * @param otherError The error of the other value to subtract from this
{@code DoubleDouble}.
+ */
+ public void subtract(final double otherValue, final double otherError) {
+ add(-otherValue, -otherError);
+ }
+
+ /**
+ * Subtracts an other double-double value from this {@code DoubleDouble},
reading the values from an array.
+ * This is a convenience method for a frequently used operation,
implemented as below:
+ *
+ * {@preformat java
+ * subtract(array[index], array[index + errorOffset]);
+ * }
+ *
+ * @param array The array from which to get the value and error.
+ * @param index Index of the value in the given array.
+ * @param errorOffset Offset to add to {@code index} in order to get the
index of the error in the given array.
+ */
+ public void subtract(final double[] array, final int index, final int
errorOffset) {
+ subtract(array[index], array[index + errorOffset]);
+ }
+
+ /**
* Multiplies this {@code DoubleDouble} by an other double-double value.
* This is a convenience method for:
*
@@ -397,6 +526,22 @@ public final class DoubleDouble extends
}
/**
+ * Multiplies this {@code DoubleDouble} by an other double-double value
stored in the given array.
+ * This is a convenience method for a frequently used operation,
implemented as below:
+ *
+ * {@preformat java
+ * multiply(array[index], array[index + errorOffset]);
+ * }
+ *
+ * @param array The array from which to get the value and error.
+ * @param index Index of the value in the given array.
+ * @param errorOffset Offset to add to {@code index} in order to get the
index of the error in the given array.
+ */
+ public void multiply(final double[] array, final int index, final int
errorOffset) {
+ multiply(array[index], array[index + errorOffset]);
+ }
+
+ /**
* Divides this {@code DoubleDouble} by an other double-double value.
* This is a convenience method for:
*
@@ -418,6 +563,11 @@ public final class DoubleDouble extends
* @param denominatorError The error of the other value by which to divide
this {@code DoubleDouble}.
*/
public void divide(final double denominatorValue, final double
denominatorError) {
+ if (STRICTFP) {
+ value /= denominatorValue;
+ error = 0;
+ return;
+ }
final double numeratorValue = value;
final double numeratorError = error;
value = denominatorValue;