sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1529261 [1/3] - in /sis/branches/JDK6: ./ application/sis-console/src/main/java/org/apache/sis/console/ core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/ core/sis-metadata/src/test/java/org/apache/sis/xml/ core/sis-referenc...
Date Fri, 04 Oct 2013 19:03:08 GMT
Author: desruisseaux
Date: Fri Oct  4 19:03:07 2013
New Revision: 1529261

URL: http://svn.apache.org/r1529261
Log:
Merge from the JDK7 branch.

Added:
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
      - copied unchanged from r1529257, sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
    sis/branches/JDK6/core/sis-utility/src/test/java/org/apache/sis/internal/util/CheckedArrayListTest.java
      - copied, changed from r1529257, sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/CheckedArrayListTest.java
    sis/branches/JDK6/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
      - copied, changed from r1529257, sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
Modified:
    sis/branches/JDK6/   (props changed)
    sis/branches/JDK6/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java
    sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/SC_VerticalCRS.java
    sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/TM_Primitive.java
    sis/branches/JDK6/core/sis-metadata/src/test/java/org/apache/sis/xml/MetadataMarshallingTest.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Solver.java
    sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/package-info.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/GeneralMatrixTest.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix1Test.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix2Test.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix3Test.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/SolverTest.java
    sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_CharacterString.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/Measure.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/ObjectReference.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/system/Supervisor.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedArrayList.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/util/UnmodifiableArrayList.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
    sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
    sis/branches/JDK6/core/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
    sis/branches/JDK6/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
    sis/branches/JDK6/core/sis-utility/src/test/java/org/apache/sis/util/ArraysExtTest.java
    sis/branches/JDK6/pom.xml

Propchange: sis/branches/JDK6/
------------------------------------------------------------------------------
  Merged /sis/branches/JDK7:r1524815-1529257

Modified: sis/branches/JDK6/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java [UTF-8] (original)
+++ sis/branches/JDK6/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -17,6 +17,7 @@
 package org.apache.sis.console;
 
 import java.util.EnumSet;
+import java.io.Console;
 import java.io.IOException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.JAXBException;
@@ -93,7 +94,14 @@ final class MetadataSC extends SubComman
                 final Marshaller marshaller = pool.acquireMarshaller();
                 marshaller.setProperty(XML.LOCALE,   locale);
                 marshaller.setProperty(XML.TIMEZONE, timezone);
-                marshaller.marshal(metadata, out);
+                if (isConsole()) {
+                    marshaller.marshal(metadata, out);
+                } else {
+                    out.flush();
+                    marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding.name());
+                    marshaller.marshal(metadata, System.out); // Use OutputStream instead than Writer.
+                    System.out.flush();
+                }
             } else {
                 final TreeTable tree = MetadataStandard.ISO_19115.asTreeTable(metadata, ValueExistencePolicy.NON_EMPTY);
                 final TreeTableFormat tf = new TreeTableFormat(locale, timezone);
@@ -104,4 +112,16 @@ final class MetadataSC extends SubComman
         }
         return 0;
     }
+
+    /**
+     * Returns {@code true} if {@link #out} is sending its output to the console.
+     * If not, then we are probably writing to a file or the user specified his own encoding.
+     * In such case, we will send the XML output to an {@code OutputStream} instead than to a
+     * {@code Writer} and let the marshaller apply the encoding itself.
+     */
+    private boolean isConsole() {
+        if (outputBuffer != null) return true; // Special case for JUnit tests only.
+        final Console console = System.console();
+        return (console != null) && console.writer() == out;
+    }
 }

Modified: sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/SC_VerticalCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/SC_VerticalCRS.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/SC_VerticalCRS.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/SC_VerticalCRS.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -16,8 +16,6 @@
  */
 package org.apache.sis.internal.jaxb.gml;
 
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
 import javax.xml.bind.annotation.XmlAnyElement;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.apache.sis.internal.jaxb.gco.PropertyType;
@@ -116,12 +114,8 @@ public class SC_VerticalCRS extends Prop
      */
     @XmlAnyElement(lax = true)
     public Object getElement() {
-        final LogRecord record = Errors.getResources(null).getLogRecord(Level.WARNING,
-                Errors.Keys.MissingRequiredModule_1, "sis-referencing");
-        record.setSourceClassName(SC_VerticalCRS.class.getName());
-        record.setSourceMethodName("getElement");
-        final Context context = Context.current();
-        Context.warningOccured(context, metadata, record);
+        Context.warningOccured(Context.current(), metadata, SC_VerticalCRS.class, "getElement",
+                Errors.class, Errors.Keys.MissingRequiredModule_1, "sis-referencing");
         return null;
     }
 

Modified: sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/TM_Primitive.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/TM_Primitive.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/TM_Primitive.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gml/TM_Primitive.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -17,8 +17,6 @@
 package org.apache.sis.internal.jaxb.gml;
 
 import java.util.Date;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
 import javax.xml.bind.annotation.XmlElement;
 import org.opengis.temporal.Period;
 import org.opengis.temporal.Instant;
@@ -128,12 +126,8 @@ public final class TM_Primitive extends 
                      * TemporalPrimitive as the source class, since it is the closest we can get
                      * to a public API.
                      */
-                    final Context context = Context.current();
-                    final LogRecord record = Errors.getResources(context != null ? context.getLocale() : null)
-                            .getLogRecord(Level.WARNING, Errors.Keys.IllegalRange_2, begin, end);
-                    record.setSourceClassName(TemporalPrimitive.class.getName());
-                    record.setSourceMethodName("setTimePeriod");
-                    Context.warningOccured(context, this, record);
+                    Context.warningOccured(Context.current(), this, TemporalPrimitive.class, "setTimePeriod",
+                            Errors.class, Errors.Keys.IllegalRange_2, begin, end);
                 } else try {
                     metadata = TemporalUtilities.createPeriod(begin, end);
                     period.copyIdTo(metadata);

Modified: sis/branches/JDK6/core/sis-metadata/src/test/java/org/apache/sis/xml/MetadataMarshallingTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-metadata/src/test/java/org/apache/sis/xml/MetadataMarshallingTest.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-metadata/src/test/java/org/apache/sis/xml/MetadataMarshallingTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-metadata/src/test/java/org/apache/sis/xml/MetadataMarshallingTest.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -26,6 +26,7 @@ import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.JAXBException;
 import org.opengis.util.InternationalString;
 import org.apache.sis.util.iso.SimpleInternationalString;
+import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.metadata.iso.extent.DefaultExtent;
 import org.apache.sis.metadata.iso.extent.DefaultTemporalExtent;
 import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
@@ -100,6 +101,26 @@ public final strictfp class MetadataMars
     }
 
     /**
+     * Tests a collection that contains no element.
+     * This was used to cause a {@code NullPointerException} prior SIS-139 fix.
+     *
+     * @throws JAXBException If an error occurred during the during unmarshalling processes.
+     *
+     * @since 0.4
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-139">SIS-139</a>
+     */
+    @Test
+    public void testEmptyCollection() throws JAXBException {
+        final String xml =
+                "<gmd:MD_Metadata xmlns:gmd=\"" + Namespaces.GMD + "\">\n" +
+                "  <gmd:contact/>\n" +
+                "</gmd:MD_Metadata>";
+        final DefaultMetadata metadata = (DefaultMetadata) XML.unmarshal(xml);
+        assertTrue(metadata.getContacts().isEmpty());
+    }
+
+    /**
      * Tests the (un)marshalling of a text group with a default {@code <gco:CharacterString>} element.
      * This test is somewhat a duplicate of {@link FreeTextMarshallingTest}, but the context is more
      * elaborated.

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -19,8 +19,6 @@ package org.apache.sis.referencing.datum
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
 import javax.measure.unit.SI;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Length;
@@ -570,11 +568,9 @@ public class DefaultEllipsoid extends Ab
      * Emits a warning telling that the given element is repeated twice.
      */
     private void warnDuplicated(final String element) {
-        final LogRecord record = Errors.getResources(null)
-                .getLogRecord(Level.WARNING, Errors.Keys.DuplicatedElement_1, element);
-        record.setSourceClassName(DefaultEllipsoid.class.getName());
-        record.setSourceMethodName("unmarshal"); // We cheat a bit since there is not such method...
-        Context.warningOccured(Context.current(), this, record);
+         // We cheat a bit for the "unmarshal" method name since there is not such method...
+        Context.warningOccured(Context.current(), this, DefaultEllipsoid.class, "unmarshal",
+                Errors.class, Errors.Keys.DuplicatedElement_1, element);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -21,11 +21,18 @@ import org.opengis.referencing.operation
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.math.MathFunctions;
+import org.apache.sis.internal.util.DoubleDouble;
 
 
 /**
  * A two dimensional array of numbers. Row and column numbering begins with zero.
  *
+ * {@section Support for extended precision}
+ * This class can optionally support extended precision using the <cite>double-double arithmetic</cite>.
+ * In extended precision mode, the {@link #elements} array have twice its normal length. The first half
+ * of the array contains the same value than in normal precision mode, while the second half contains
+ * the {@link DoubleDouble#error}.
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4 (derived from geotk-2.2)
  * @version 0.4
@@ -42,6 +49,10 @@ class GeneralMatrix extends MatrixSIS {
     /**
      * All matrix elements in a flat, row-major (column indices vary fastest) array.
      * The array length is <code>{@linkplain #numRow} * {@linkplain #numCol}</code>.
+     *
+     * <p>In <cite>extended precision mode</cite>, the length of this array is actually twice the above-cited length.
+     * The first half contains {@link DoubleDouble#value}, and the second half contains the {@link DoubleDouble#error}
+     * for each value in the first half.</p>
      */
     final double[] elements;
 
@@ -60,12 +71,14 @@ class GeneralMatrix extends MatrixSIS {
      * @param numCol Number of columns.
      * @param setToIdentity {@code true} for initializing the matrix to the identity matrix,
      *        or {@code false} for leaving it initialized to zero.
+     * @param precision 1 for normal precision, or 2 for extended precision.
+     *        No other value is allowed (this is not verified).
      */
-    GeneralMatrix(final int numRow, final int numCol, final boolean setToIdentity) {
+    GeneralMatrix(final int numRow, final int numCol, final boolean setToIdentity, final int precision) {
         ensureValidSize(numRow, numCol);
         this.numRow = (short) numRow;
         this.numCol = (short) numCol;
-        elements = new double[numRow * numCol];
+        elements = new double[numRow * numCol * precision];
         if (setToIdentity) {
             final int stop = Math.min(numRow, numCol) * numCol;
             for (int i=0; i<stop; i += numCol+1) {
@@ -85,7 +98,7 @@ class GeneralMatrix extends MatrixSIS {
      */
     GeneralMatrix(final int numRow, final int numCol, final double[] elements) {
         ensureValidSize(numRow, numCol);
-        ensureLengthMatch(numRow*numCol, elements);
+        ensureLengthMatch(numRow * numCol, elements);
         this.numRow = (short) numRow;
         this.numCol = (short) numCol;
         this.elements = elements.clone();
@@ -103,11 +116,7 @@ class GeneralMatrix extends MatrixSIS {
         this.numRow = (short) numRow;
         this.numCol = (short) numCol;
         elements = new double[numRow * numCol];
-        for (int k=0,j=0; j<numRow; j++) {
-            for (int i=0; i<numCol; i++) {
-                elements[k++] = matrix.getElement(j, i);
-            }
-        }
+        getElements(matrix, numRow, numCol, elements);
     }
 
     /**
@@ -120,6 +129,64 @@ 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.
+     *
+     * @param matrix   The matrix to copy.
+     * @param numRow   The number of rows to copy (usually {@code matrix.getNumRow()}).
+     * @param numCol   The number of columns to copy (usually {@code matrix.getNumCol()}).
+     * @param elements Where to copy the elements.
+     */
+    private static void getElements(final Matrix matrix, final int numRow, final int numCol, final double[] elements) {
+        if (matrix instanceof MatrixSIS) {
+            ((MatrixSIS) matrix).getElements(elements);
+        } else {
+            for (int k=0,j=0; j<numRow; j++) {
+                for (int i=0; i<numCol; i++) {
+                    elements[k++] = matrix.getElement(j, i);
+                }
+            }
+        }
+    }
+
+    /**
+     * Infers all {@link DoubleDouble#error} with a default values inferred from {@link DoubleDouble#value}.
+     * For example if a matrix element is exactly 3.141592653589793, there is good chances that the user's
+     * intend was to specify the {@link Math#PI} value, in which case this method will infer that we would
+     * need to add 1.2246467991473532E-16 in order to get a value closer to π.
+     */
+    private static void inferErrors(final double[] elements) {
+        final int length = elements.length / 2;
+        for (int i=length; i<elements.length; i++) {
+            elements[i] = DoubleDouble.errorForWellKnownValue(elements[i - length]);
+        }
+    }
+
+    /**
+     * Returns the index of the first {@link DoubleDouble#error} value in the {@link #elements} array,
+     * or 0 if none. This method returns a non-zero value only if the matrix has been created in extended
+     * precision mode.
+     */
+    static int indexOfErrors(final int numRow, final int numCol, final double[] elements) {
+        assert elements.length % (numRow * numCol) == 0;
+        return (numRow * numCol) % elements.length; // A % B is for getting 0 without branching if A == B.
+    }
+
+    /**
      * Ensures that the given matrix size is valid for this {@code GeneralMatrix} implementation.
      */
     private static void ensureValidSize(final int numRow, final int numCol) {
@@ -169,38 +236,91 @@ class GeneralMatrix extends MatrixSIS {
     @Override
     public final void setElement(final int row, final int column, final double value) {
         if (row >= 0 && row < numRow && column >= 0 && column < numCol) {
-            elements[row * numCol + column] = value;
+            int i = row * numCol + column;
+            elements[i] = value;
+            i += numRow * numCol;
+            if (i < elements.length) {
+                elements[i] = DoubleDouble.errorForWellKnownValue(value);
+            }
         } else {
             throw indexOutOfBounds(row, column);
         }
     }
 
     /**
+     * Returns all elements of the given matrix followed by the error terms for extended-precision arithmetic.
+     * The array will have twice the normal length. See {@link #elements} for more discussion.
+     *
+     * <p>This method may return a direct reference to the internal array. <strong>Do not modify.</strong>,
+     * unless the {@code copy} argument is {@code true}.</p>
+     *
+     * @param copy If {@code true}, then the returned array is guaranteed to be a copy, never the internal array.
+     */
+    static double[] getExtendedElements(final Matrix matrix, final int numRow, final int numCol, final boolean copy) {
+        double[] elements;
+        final int length = numRow * numCol * 2;
+        if (matrix instanceof GeneralMatrix) {
+            elements = ((GeneralMatrix) matrix).elements;
+            if (elements.length == length) {
+                if (copy) {
+                    elements = elements.clone();
+                }
+                return elements; // Internal array already uses extended precision.
+            } else {
+                elements = Arrays.copyOf(elements, length);
+            }
+        } else {
+            elements = new double[length];
+            getElements(matrix, numRow, numCol, elements);
+        }
+        inferErrors(elements);
+        return elements;
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
     public final double[] getElements() {
-        return elements.clone();
+        return Arrays.copyOf(elements, numRow*numCol);
+    }
+
+    /**
+     * Copies the matrix elements in the given flat array. This method does not verify the array length,
+     * since the destination array may contain room for {@link DoubleDouble#error} terms.
+     */
+    @Override
+    final void getElements(final double[] dest) {
+        System.arraycopy(elements, 0, dest, 0, numRow*numCol);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public final void setElements(final double[] elements) {
-        ensureLengthMatch(this.elements.length, elements);
-        System.arraycopy(elements, 0, this.elements, 0, elements.length);
+    public final void setElements(final double[] newValues) {
+        ensureLengthMatch(numRow*numCol, newValues);
+        System.arraycopy(newValues, 0, elements, 0, newValues.length);
+        if (elements.length != newValues.length) {
+            inferErrors(newValues);
+        }
     }
 
     /**
      * {@inheritDoc}
+     *
+     * <p>This method does not check the error terms, because those terms are not visible to the user
+     * (they can not appear in the value returned by {@link #getElement(int, int)}, and are not shown
+     * by {@link #toString()}) - returning {@code false} while the matrix clearly looks like affine
+     * would be confusing for the user. Furthermore, the errors can be non-zero only in the very last
+     * element and that value always smaller than 2.3E-16.</p>
      */
     @Override
     public final boolean isAffine() {
         final int numRow = this.numRow; // Protection against accidental changes.
         final int numCol = this.numCol;
         if (numRow == numCol) {
-            int i = elements.length;
+            int i = numRow * numCol;
             if (elements[--i] == 1) {
                 final int base = (numRow - 1) * numCol;
                 while (--i >= base) {
@@ -216,6 +336,16 @@ class GeneralMatrix extends MatrixSIS {
 
     /**
      * {@inheritDoc}
+     *
+     * <p>This method does not check the error terms, because those terms are not visible to the user
+     * (they can not appear in the value returned by {@link #getElement(int, int)}, and are not shown
+     * by {@link #toString()}) - returning {@code false} while the matrix clearly looks like identity
+     * would be confusing for the user. Furthermore, the errors can be non-zero only on the diagonal,
+     * and those values always smaller than 2.3E-16.</p>
+     *
+     * <p>An other argument is that the extended precision is for reducing rounding errors during
+     * matrix arithmetics. But since the user provided the original data as {@code double} values,
+     * the extra precision usually have no "real" meaning.</p>
      */
     @Override
     public final boolean isIdentity() {
@@ -225,7 +355,8 @@ class GeneralMatrix extends MatrixSIS {
             return false;
         }
         int di = 0; // Index of next diagonal element.
-        for (int i=0; i<elements.length; i++) {
+        final int length = numRow * numCol;
+        for (int i=0; i<length; i++) {
             final double element = elements[i];
             if (i == di) {
                 if (element != 1) return false;
@@ -247,15 +378,24 @@ class GeneralMatrix extends MatrixSIS {
     public void transpose() {
         final int numRow = this.numRow; // Protection against accidental changes.
         final int numCol = this.numCol;
+        final int errors = indexOfErrors(numRow, numCol, elements); // Where error values start, or 0 if none.
         for (int j=0; j<numRow; j++) {
             for (int i=0; i<j; i++) {
-                ArraysExt.swap(elements, j*numCol + i, i*numCol + j);
+                final int lo = j*numCol + i;
+                final int up = i*numCol + j;
+                ArraysExt.swap(elements, lo, up);
+                if (errors != 0) {
+                    // Swap also the error terms in extended precision mode.
+                    ArraysExt.swap(elements, lo + errors, up + errors);
+                }
             }
         }
     }
 
     /**
      * {@inheritDoc}
+     *
+     * <p>The current implementation discards the extended precision, if any.</p>
      */
     @Override
     public final void normalizeColumns() {
@@ -271,45 +411,49 @@ class GeneralMatrix extends MatrixSIS {
                 elements[j*numCol + i] /= m;
             }
         }
+        Arrays.fill(elements, numRow * numCol, elements.length, 0);
     }
 
     /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS inverse() throws NoninvertibleMatrixException {
-        return Solver.inverse(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS solve(final Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException {
-        throw new UnsupportedOperationException(); // TODO
-    }
-
-    /**
-     * {@inheritDoc}
+     * Sets this matrix to the product of the given matrices: {@code this = A × B}.
+     * The matrix sizes much match - this is not verified unless assertions are enabled.
      */
-    @Override
-    public final MatrixSIS multiply(final Matrix matrix) {
+    final void setToProduct(final MatrixSIS A, final Matrix B) {
         final int numRow = this.numRow; // Protection against accidental changes.
         final int numCol = this.numCol;
-        final int nc = matrix.getNumCol();
-        ensureNumRowMatch(numCol, matrix, nc);
-        final MatrixSIS result = Matrices.createZero(numRow, nc);
-        for (int j=0; j<numRow; j++) {
-            final int srcOff = j * numCol;
-            for (int i=0; i<nc; i++) {
-                double sum = 0;
-                for (int k=0; k<numCol; k++) {
-                    sum += elements[srcOff + k] * matrix.getElement(k, i);
+        final int nc = A.getNumCol();
+        assert B.getNumRow() == nc;
+        assert numRow == A.getNumRow() && numCol == B.getNumCol();
+        /*
+         * Get the matrix element values, together with the error terms if the matrix
+         * use extended precision (double-double arithmetic).
+         */
+        final double[] eltA   = getExtendedElements(A, numRow, nc, false);
+        final double[] eltB   = getExtendedElements(B, nc, numCol, false);
+        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'.
+         */
+        final DoubleDouble dot = new DoubleDouble();
+        final DoubleDouble sum = new DoubleDouble();
+        for (int k=0,j=0; j<numRow; j++) {
+            for (int i=0; i<numCol; i++) {
+                sum.clear();
+                int iB = i;       // Index of values in a single column of B.
+                int iA = j * nc;  // Index of values in a single row of A.
+                final int nextRow = iA + nc;
+                while (iA < nextRow) {
+                    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.
                 }
-                result.setElement(j, i, sum);
+                sum.storeTo(elements, k++, errorOffset);
             }
         }
-        return result;
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -44,22 +44,20 @@ import org.apache.sis.internal.jdk7.Obje
  *       {@link #createIdentity createIdentity},
  *       {@link #createDiagonal createDiagonal},
  *       {@link #createZero     createZero},
- *       {@link #create         create}.
+ *       {@link #create         create},
+ *       {@link #copy           copy}.
  *   </li>
  *   <li>Creating new matrices for coordinate operation steps:
  *       {@link #createTransform(Envelope, AxisDirection[], Envelope, AxisDirection[]) createTransform},
  *       {@link #createDimensionSelect createDimensionSelect},
  *       {@link #createPassThrough     createPassThrough}.
  *   </li>
- *   <li>Copies matrices to a SIS implementation:
- *       {@link #copy       copy},
- *       {@link #castOrCopy castOrCopy}.
- *   </li>
  *   <li>Information:
  *       {@link #isAffine   isAffine},
  *       {@link #isIdentity isIdentity},
  *       {@link #equals(Matrix, Matrix, double, boolean) equals},
- *       {@link #equals(Matrix, Matrix, ComparisonMode)  equals}.
+ *       {@link #equals(Matrix, Matrix, ComparisonMode)  equals},
+ *       {@link #toString(Matrix) toString}.
  *   </li>
  * </ul>
  *
@@ -72,7 +70,7 @@ public final class Matrices extends Stat
     /**
      * Number of spaces to put between columns formatted by {@link #toString(Matrix)}.
      */
-    private static final int MARGIN = 2;
+    private static final int SPACING = 2;
 
     /**
      * Do not allows instantiation of this class.
@@ -101,7 +99,7 @@ public final class Matrices extends Stat
             case 2:  return new Matrix2();
             case 3:  return new Matrix3();
             case 4:  return new Matrix4();
-            default: return new GeneralMatrix(size, size, true);
+            default: return new GeneralMatrix(size, size, true, 1);
         }
     }
 
@@ -125,7 +123,7 @@ public final class Matrices extends Stat
         if (numRow == numCol) {
             return createIdentity(numRow);
         } else {
-            return new NonSquareMatrix(numRow, numCol, true);
+            return new NonSquareMatrix(numRow, numCol, true, 1);
         }
     }
 
@@ -150,9 +148,9 @@ public final class Matrices extends Stat
             case 2:  return new Matrix2(false);
             case 3:  return new Matrix3(false);
             case 4:  return new Matrix4(false);
-            default: return new GeneralMatrix(numRow, numCol, false);
+            default: return new GeneralMatrix(numRow, numCol, false, 1);
         }
-        return new NonSquareMatrix(numRow, numCol, false);
+        return new NonSquareMatrix(numRow, numCol, false, 1);
     }
 
     /**
@@ -647,37 +645,23 @@ public final class Matrices extends Stat
      * @return A copy of the given matrix, or {@code null} if the given matrix was null.
      *
      * @see MatrixSIS#clone()
+     * @see MatrixSIS#castOrCopy(Matrix)
      */
     public static MatrixSIS copy(final Matrix matrix) {
         if (matrix == null) {
             return null;
         }
         final int size = matrix.getNumRow();
-        if (size == matrix.getNumCol()) {
-            switch (size) {
-                case 1: return new Matrix1(matrix);
-                case 2: return new Matrix2(matrix);
-                case 3: return new Matrix3(matrix);
-                case 4: return new Matrix4(matrix);
-            }
+        if (size != matrix.getNumCol()) {
+            return new NonSquareMatrix(matrix);
         }
-        return new GeneralMatrix(matrix);
-    }
-
-    /**
-     * Casts or copies the given matrix to a SIS implementation. If {@code matrix} is already
-     * an instance of {@code MatrixSIS}, then it is returned unchanged. Otherwise all elements
-     * are copied in a new {@code MatrixSIS} object.
-     *
-     * @param  matrix The matrix to cast or copy, or {@code null}.
-     * @return The matrix argument if it can be safely casted (including {@code null} argument),
-     *         or a copy of the given matrix otherwise.
-     */
-    public static MatrixSIS castOrCopy(final Matrix matrix) {
-        if (matrix instanceof MatrixSIS) {
-            return (MatrixSIS) matrix;
+        switch (size) {
+            case 1: return new Matrix1(matrix);
+            case 2: return new Matrix2(matrix);
+            case 3: return new Matrix3(matrix);
+            case 4: return new Matrix4(matrix);
         }
-        return copy(matrix);
+        return new GeneralMatrix(matrix);
     }
 
     /**
@@ -717,6 +701,11 @@ public final class Matrices extends Stat
      * of identical size, and returning {@code true} if and only if all differences are smaller than or equal
      * to {@code tolerance}.
      *
+     * <p><b>Caution:</b> {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters},
+     * when represented as a matrix, are close to an identity transform and could easily be confused with rounding
+     * errors. In case of doubt, it is often safer to use the strict {@link MatrixSIS#isIdentity()} method instead
+     * than this one.</p>
+     *
      * @param  matrix The matrix to test for identity.
      * @param  tolerance The tolerance value, or 0 for a strict comparison.
      * @return {@code true} if this matrix is close to the identity matrix given the tolerance threshold.
@@ -843,6 +832,25 @@ public final class Matrices extends Stat
      * Returns a unlocalized string representation of the given matrix.
      * For each column, the numbers are aligned on the decimal separator.
      *
+     * <p>The current implementation formats ±0 and ±1 without trailing {@code ".0"}, and all other values with
+     * a per-column uniform number of fraction digits. The ±0 and ±1 values are treated especially because they
+     * usually imply a "<cite>no scale</cite>", "<cite>no translation</cite>" or "<cite>orthogonal axes</cite>"
+     * meaning. A matrix in SIS is often populated mostly by ±0 and ±1 values, with a few "interesting" values.
+     * The simpler ±0 and ±1 formatting makes easier to spot the "interesting" values.</p>
+     *
+     * <p>The following example shows the string representation of an affine transform which swap
+     * (<var>latitude</var>, <var>longitude</var>) axes, converts degrees to radians and converts
+     * height values from feet to metres:</p>
+     *
+     * {@preformat math
+     *   ┌                                                       ┐
+     *   │ 0                     0.017453292519943295  0       0 │
+     *   │ 0.017453292519943295  0                     0       0 │
+     *   │ 0                     0                     0.3048  0 │
+     *   │ 0                     0                     0       1 │
+     *   └                                                       ┘
+     * }
+     *
      * {@note Formatting on a per-column basis is convenient for the kind of matrices used in referencing by coordinates,
      *        because each column is typically a displacement vector in a different dimension of the source coordinate
      *        reference system. In addition, the last column is often a translation vector having a magnitude very
@@ -854,53 +862,92 @@ public final class Matrices extends Stat
     public static String toString(final Matrix matrix) {
         final int numRow = matrix.getNumRow();
         final int numCol = matrix.getNumCol();
-        final String[] elements = new String[numRow * numCol];
-        final int[] columnWidth = new int[numCol];
-        final int[] maximumFractionDigits = new int[numCol];
-        final int[] maximumRemainingWidth = new int[numCol]; // Minus sign (if any) + integer digits + decimal separator + 2 spaces.
+        final String[]  elements            = new String [numCol * numRow];
+        final boolean[] noFractionDigits    = new boolean[numCol * numRow];
+        final boolean[] hasDecimalSeparator = new boolean[numCol];
+        final int[] maximumFractionDigits   = new int    [numCol];
+        final int[] widthBeforeFraction     = new int    [numCol]; // spacing + ('-') + integerDigits + '.'
+        final int[] columnWidth             = new int    [numCol];
         int totalWidth = 1;
         /*
          * Create now the string representation of all matrix elements and measure the width
          * of the integer field and the fraction field, then the total width of each column.
          */
-        int margin = 1; // Margin before the first column only.
+        int spacing = 1; // Spacing is 1 before the first column only, then SPACING for other columns.
         for (int i=0; i<numCol; i++) {
             for (int j=0; j<numRow; j++) {
-                final String element = Double.toString(matrix.getElement(j,i)).replace("Infinity", "∞");
-                elements[j*numCol + i] = element;
-                int width = element.length();
-                int s = element.lastIndexOf('.');
-                if (s >= 0) {
-                    width = (maximumRemainingWidth[i] = Math.max(maximumRemainingWidth[i], ++s + margin))
-                          + (maximumFractionDigits[i] = Math.max(maximumFractionDigits[i], width - s));
+                final int flatIndex = j*numCol + i;
+                final double value  = matrix.getElement(j,i);
+                String element = Double.toString(value);
+                final int width;
+                /*
+                 * Special case for ±0 and ±1 (because those values appear very often and have
+                 * a particular meaning): for those values, we will ignore the fraction digits.
+                 * For all other values, we will format all fraction digits.
+                 */
+                if (value == -1 || value == 0 || value == +1) {
+                    noFractionDigits[flatIndex] = true;
+                    width = spacing + element.length() - 2; // The -2 is for ignoring the trailing ".0"
+                    widthBeforeFraction[i] = Math.max(widthBeforeFraction[i], width);
                 } else {
-                    // NaN or Infinity.
-                    width += margin;
+                    /*
+                     * All values other than ±0 and ±1. Store separately the width before and after
+                     * the decimal separator. The width before the separator contains the spacing.
+                     */
+                    int s = element.lastIndexOf('.');
+                    if (s >= 0) {
+                        s++; // After the separator.
+                        hasDecimalSeparator[i] = true;
+                        width = (widthBeforeFraction  [i] = Math.max(widthBeforeFraction  [i], spacing + s))
+                              + (maximumFractionDigits[i] = Math.max(maximumFractionDigits[i], element.length() - s));
+                    } else {
+                        // NaN or Infinity.
+                        element = element.replace("Infinity", "∞");
+                        width = spacing + element.length();
+                    }
                 }
                 columnWidth[i] = Math.max(columnWidth[i], width);
+                elements[flatIndex] = element;
             }
             totalWidth += columnWidth[i];
-            margin = MARGIN; // Margin before all columns after the first one.
+            spacing = SPACING; // Specing before all columns after the first one.
         }
         /*
-         * Now append the formatted elements with the appropriate amount of spaces
-         * and trailling zeros for each column.
+         * Now append the formatted elements with the appropriate amount of spaces before each value,
+         * and trailling zeros after each value except ±0, ±1, NaN and infinities.
          */
-        final String lineSeparator = JDK7.lineSeparator();
+        final String   lineSeparator = JDK7.lineSeparator();
         final CharSequence whiteLine = CharSequences.spaces(totalWidth);
-        final StringBuffer buffer = new StringBuffer((totalWidth + 2 + lineSeparator.length()) * (numRow + 2));
+        final StringBuilder   buffer = new StringBuilder((totalWidth + 2 + lineSeparator.length()) * (numRow + 2));
         buffer.append('┌').append(whiteLine).append('┐').append(lineSeparator);
-        for (int k=0,j=0; j<numRow; j++) {
+        int flatIndex = 0;
+        for (int j=0; j<numRow; j++) {
             buffer.append('│');
             for (int i=0; i<numCol; i++) {
-                final String element = elements[k++];
+                final String element = elements[flatIndex];
                 final int width = element.length();
-                int s = element.lastIndexOf('.');
-                buffer.append(CharSequences.spaces(s >= 0 ? maximumRemainingWidth[i] - ++s : columnWidth[i] - width)).append(element);
+                int spaces, s = element.lastIndexOf('.');
+                if (s >= 0) {
+                    if (hasDecimalSeparator[i]) s++;
+                    spaces = widthBeforeFraction[i] - s; // Number of spaces for alignment on the decimal separator
+                } else {
+                    spaces = columnWidth[i] - width; // Number of spaces for right alignment (NaN or ∞ cases)
+                }
+                buffer.append(CharSequences.spaces(spaces)).append(element);
+                /*
+                 * Append trailing spaces for ±0 and ±1 values,
+                 * or trailing zeros for all other real values.
+                 */
                 s += maximumFractionDigits[i] - width;
-                while (--s >= 0) {
-                    buffer.append('0');
+                if (noFractionDigits[flatIndex]) {
+                    buffer.setLength(buffer.length() - 2); // Erase the trailing ".0"
+                    buffer.append(CharSequences.spaces(s + 2));
+                } else {
+                    while (--s >= 0) {
+                        buffer.append('0');
+                    }
                 }
+                flatIndex++;
             }
             buffer.append(" │").append(lineSeparator);
         }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -84,6 +84,9 @@ public final class Matrix1 extends Matri
      *
      * @param elements Elements of the matrix.
      * @throws IllegalArgumentException If the given array does not have the expected length.
+     *
+     * @see #setElements(double[])
+     * @see Matrices#create(int, int, double[])
      */
     public Matrix1(final double[] elements) throws IllegalArgumentException {
         setElements(elements);
@@ -100,6 +103,24 @@ public final class Matrix1 extends Matri
         m00 = matrix.getElement(0,0);
     }
 
+    /**
+     * Casts or copies the given matrix to a {@code Matrix1} implementation. If the given {@code matrix}
+     * is already an instance of {@code Matrix1}, then it is returned unchanged. Otherwise this method
+     * verifies the matrix size, then copies the element in a new {@code Matrix1} object.
+     *
+     * @param  matrix The matrix to cast or copy, or {@code null}.
+     * @return The matrix argument if it can be safely casted (including {@code null} argument),
+     *         or a copy of the given matrix otherwise.
+     * @throws MismatchedMatrixSizeException If the size of the given matrix is not {@value #SIZE}×{@value #SIZE}.
+     */
+    public static Matrix1 castOrCopy(final Matrix matrix) throws MismatchedMatrixSizeException {
+        if (matrix == null || matrix instanceof Matrix1) {
+            return (Matrix1) matrix;
+        }
+        ensureSizeMatch(SIZE, matrix);
+        return new Matrix1(matrix);
+    }
+
     /*
      * The 'final' modifier in following method declarations is redundant with the 'final' modifier
      * in this class declaration, but we keep them as a reminder of which methods should stay final
@@ -173,7 +194,18 @@ public final class Matrix1 extends Matri
      */
     @Override
     public final double[] getElements() {
-        return new double[] {m00};
+        final double[] elements = new double[SIZE*SIZE];
+        getElements(elements);
+        return elements;
+    }
+
+    /**
+     * Copies the matrix elements in the given flat array.
+     * The array length shall be at least 1, may also be 2.
+     */
+    @Override
+    final void getElements(final double[] elements) {
+        elements[0] = m00;
     }
 
     /**
@@ -220,50 +252,6 @@ public final class Matrix1 extends Matri
     }
 
     /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS inverse() throws NoninvertibleMatrixException {
-        if (m00 == 0) {
-            throw new NoninvertibleMatrixException();
-        }
-        return new Matrix1(1 / m00);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS solve(final Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException {
-        final int nc = matrix.getNumCol();
-        ensureNumRowMatch(SIZE, matrix, nc);
-        if (m00 == 0) {
-            throw new NoninvertibleMatrixException();
-        }
-        if (nc != SIZE) {
-            final NonSquareMatrix m = new NonSquareMatrix(SIZE, nc, false);
-            for (int i=0; i<nc; i++) {
-                m.elements[i] = matrix.getElement(0, i) / m00;
-            }
-            return m;
-        }
-        return new Matrix1(matrix.getElement(0,0) / m00);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS multiply(final Matrix matrix) {
-        final int nc = matrix.getNumCol();
-        ensureNumRowMatch(SIZE, matrix, nc);
-        if (nc != SIZE) {
-            return new NonSquareMatrix(this, matrix);
-        }
-        return new Matrix1(m00 * matrix.getElement(0,0));
-    }
-
-    /**
      * Returns {@code true} if the specified object is of type {@code Matrix1} and
      * all of the data members are equal to the corresponding data members in this matrix.
      *

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -81,10 +81,8 @@ public final class Matrix2 extends Matri
     public Matrix2(final double m00, final double m01,
                    final double m10, final double m11)
     {
-        this.m00 = m00;
-        this.m01 = m01;
-        this.m10 = m10;
-        this.m11 = m11;
+        this.m00 = m00;    this.m01 = m01;
+        this.m10 = m10;    this.m11 = m11;
     }
 
     /**
@@ -93,6 +91,9 @@ public final class Matrix2 extends Matri
      *
      * @param elements Elements of the matrix. Column indices vary fastest.
      * @throws IllegalArgumentException If the given array does not have the expected length.
+     *
+     * @see #setElements(double[])
+     * @see Matrices#create(int, int, double[])
      */
     public Matrix2(final double[] elements) throws IllegalArgumentException {
         setElements(elements);
@@ -112,6 +113,24 @@ public final class Matrix2 extends Matri
         m11 = matrix.getElement(1,1);
     }
 
+    /**
+     * Casts or copies the given matrix to a {@code Matrix2} implementation. If the given {@code matrix}
+     * is already an instance of {@code Matrix2}, then it is returned unchanged. Otherwise this method
+     * verifies the matrix size, then copies all elements in a new {@code Matrix2} object.
+     *
+     * @param  matrix The matrix to cast or copy, or {@code null}.
+     * @return The matrix argument if it can be safely casted (including {@code null} argument),
+     *         or a copy of the given matrix otherwise.
+     * @throws MismatchedMatrixSizeException If the size of the given matrix is not {@value #SIZE}×{@value #SIZE}.
+     */
+    public static Matrix2 castOrCopy(final Matrix matrix) throws MismatchedMatrixSizeException {
+        if (matrix == null || matrix instanceof Matrix2) {
+            return (Matrix2) matrix;
+        }
+        ensureSizeMatch(SIZE, matrix);
+        return new Matrix2(matrix);
+    }
+
     /*
      * The 'final' modifier in following method declarations is redundant with the 'final' modifier
      * in this class declaration, but we keep them as a reminder of which methods should stay final
@@ -193,7 +212,19 @@ public final class Matrix2 extends Matri
      */
     @Override
     public final double[] getElements() {
-        return new double[] {m00, m01, m10, m11};
+        final double[] elements = new double[SIZE*SIZE];
+        getElements(elements);
+        return elements;
+    }
+
+    /**
+     * Copies the matrix elements in the given flat array.
+     * The array length shall be at least 4, may also be 8.
+     */
+    @Override
+    final void getElements(final double[] elements) {
+        elements[0] = m00;    elements[1] = m01;
+        elements[2] = m10;    elements[3] = m11;
     }
 
     /**
@@ -203,10 +234,8 @@ public final class Matrix2 extends Matri
     @Override
     public final void setElements(final double[] elements) {
         ensureLengthMatch(SIZE*SIZE, elements);
-        m00 = elements[0];
-        m01 = elements[1];
-        m10 = elements[2];
-        m11 = elements[3];
+        m00 = elements[0];    m01 = elements[1];
+        m10 = elements[2];    m11 = elements[3];
     }
 
     /**
@@ -247,44 +276,6 @@ public final class Matrix2 extends Matri
     }
 
     /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS inverse() throws NoninvertibleMatrixException {
-        final double det = m00*m11 - m01*m10;
-        if (det == 0) {
-            throw new NoninvertibleMatrixException();
-        }
-        return new Matrix2(m11 / det, -m01 / det,
-                          -m10 / det,  m00 / det);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS solve(final Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException {
-        throw new UnsupportedOperationException(); // TODO
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS multiply(final Matrix matrix) {
-        final int nc = matrix.getNumCol();
-        ensureNumRowMatch(SIZE, matrix, nc);
-        if (nc != SIZE) {
-            return new NonSquareMatrix(this, matrix);
-        }
-        final Matrix2 k = (matrix instanceof Matrix2) ? (Matrix2) matrix : new Matrix2(matrix);
-        return new Matrix2(m00 * k.m00  +  m01 * k.m10,
-                           m00 * k.m01  +  m01 * k.m11,
-                           m10 * k.m00  +  m11 * k.m10,
-                           m10 * k.m01  +  m11 * k.m11);
-    }
-
-    /**
      * Returns {@code true} if the specified object is of type {@code Matrix2} and
      * all of the data members are equal to the corresponding data members in this matrix.
      *

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -90,19 +90,13 @@ public final class Matrix3 extends Matri
      * @param m21 The second matrix element in the third row.
      * @param m22 The third matrix element in the third row.
      */
-    public Matrix3(double m00, double m01, double m02,
-                   double m10, double m11, double m12,
-                   double m20, double m21, double m22)
+    public Matrix3(final double m00, final double m01, final double m02,
+                   final double m10, final double m11, final double m12,
+                   final double m20, final double m21, final double m22)
     {
-        this.m00 = m00;
-        this.m01 = m01;
-        this.m02 = m02;
-        this.m10 = m10;
-        this.m11 = m11;
-        this.m12 = m12;
-        this.m20 = m20;
-        this.m21 = m21;
-        this.m22 = m22;
+        this.m00 = m00;    this.m01 = m01;    this.m02 = m02;
+        this.m10 = m10;    this.m11 = m11;    this.m12 = m12;
+        this.m20 = m20;    this.m21 = m21;    this.m22 = m22;
     }
 
     /**
@@ -111,6 +105,9 @@ public final class Matrix3 extends Matri
      *
      * @param elements Elements of the matrix. Column indices vary fastest.
      * @throws IllegalArgumentException If the given array does not have the expected length.
+     *
+     * @see #setElements(double[])
+     * @see Matrices#create(int, int, double[])
      */
     public Matrix3(final double[] elements) throws IllegalArgumentException {
         setElements(elements);
@@ -131,6 +128,24 @@ public final class Matrix3 extends Matri
         }
     }
 
+    /**
+     * Casts or copies the given matrix to a {@code Matrix3} implementation. If the given {@code matrix}
+     * is already an instance of {@code Matrix3}, then it is returned unchanged. Otherwise this method
+     * verifies the matrix size, then copies all elements in a new {@code Matrix3} object.
+     *
+     * @param  matrix The matrix to cast or copy, or {@code null}.
+     * @return The matrix argument if it can be safely casted (including {@code null} argument),
+     *         or a copy of the given matrix otherwise.
+     * @throws MismatchedMatrixSizeException If the size of the given matrix is not {@value #SIZE}×{@value #SIZE}.
+     */
+    public static Matrix3 castOrCopy(final Matrix matrix) throws MismatchedMatrixSizeException {
+        if (matrix == null || matrix instanceof Matrix3) {
+            return (Matrix3) matrix;
+        }
+        ensureSizeMatch(SIZE, matrix);
+        return new Matrix3(matrix);
+    }
+
     /*
      * The 'final' modifier in following method declarations is redundant with the 'final' modifier
      * in this class declaration, but we keep them as a reminder of which methods should stay final
@@ -222,11 +237,20 @@ public final class Matrix3 extends Matri
      */
     @Override
     public final double[] getElements() {
-        return new double[] {
-            m00, m01, m02,
-            m10, m11, m12,
-            m20, m21, m22
-        };
+        final double[] elements = new double[SIZE*SIZE];
+        getElements(elements);
+        return elements;
+    }
+
+    /**
+     * Copies the matrix elements in the given flat array.
+     * The array length shall be at least 9, may also be 18.
+     */
+    @Override
+    final void getElements(final double[] elements) {
+        elements[0] = m00;    elements[1] = m01;    elements[2] = m02;
+        elements[3] = m10;    elements[4] = m11;    elements[5] = m12;
+        elements[6] = m20;    elements[7] = m21;    elements[8] = m22;
     }
 
     /**
@@ -236,15 +260,9 @@ public final class Matrix3 extends Matri
     @Override
     public final void setElements(final double[] elements) {
         ensureLengthMatch(SIZE*SIZE, elements);
-        m00 = elements[0];
-        m01 = elements[1];
-        m02 = elements[2];
-        m10 = elements[3];
-        m11 = elements[4];
-        m12 = elements[5];
-        m20 = elements[6];
-        m21 = elements[7];
-        m22 = elements[8];
+        m00 = elements[0];    m01 = elements[1];    m02 = elements[2];
+        m10 = elements[3];    m11 = elements[4];    m12 = elements[5];
+        m20 = elements[6];    m21 = elements[7];    m22 = elements[8];
     }
 
     /**
@@ -289,44 +307,6 @@ public final class Matrix3 extends Matri
     }
 
     /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS inverse() throws NoninvertibleMatrixException {
-        return Solver.inverse(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS solve(final Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException {
-        throw new UnsupportedOperationException(); // TODO
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS multiply(final Matrix matrix) {
-        final int nc = matrix.getNumCol();
-        ensureNumRowMatch(SIZE, matrix, nc);
-        if (nc != SIZE) {
-            return new NonSquareMatrix(this, matrix);
-        }
-        final Matrix3 k = (matrix instanceof Matrix3) ? (Matrix3) matrix : new Matrix3(matrix);
-        return new Matrix3(m00 * k.m00  +  m01 * k.m10  +  m02 * k.m20,
-                           m00 * k.m01  +  m01 * k.m11  +  m02 * k.m21,
-                           m00 * k.m02  +  m01 * k.m12  +  m02 * k.m22,
-                           m10 * k.m00  +  m11 * k.m10  +  m12 * k.m20,
-                           m10 * k.m01  +  m11 * k.m11  +  m12 * k.m21,
-                           m10 * k.m02  +  m11 * k.m12  +  m12 * k.m22,
-                           m20 * k.m00  +  m21 * k.m10  +  m22 * k.m20,
-                           m20 * k.m01  +  m21 * k.m11  +  m22 * k.m21,
-                           m20 * k.m02  +  m21 * k.m12  +  m22 * k.m22);
-    }
-
-    /**
      * Returns {@code true} if the specified object is of type {@code Matrix3} and
      * all of the data members are equal to the corresponding data members in this matrix.
      *

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -105,27 +105,15 @@ public final class Matrix4 extends Matri
      * @param m32 The third matrix element in the forth row.
      * @param m33 The forth matrix element in the forth row.
      */
-    public Matrix4(double m00, double m01, double m02, double m03,
-                   double m10, double m11, double m12, double m13,
-                   double m20, double m21, double m22, double m23,
-                   double m30, double m31, double m32, double m33)
+    public Matrix4(final double m00, final double m01, final double m02, final double m03,
+                   final double m10, final double m11, final double m12, final double m13,
+                   final double m20, final double m21, final double m22, final double m23,
+                   final double m30, final double m31, final double m32, final double m33)
     {
-        this.m00 = m00;
-        this.m01 = m01;
-        this.m02 = m02;
-        this.m03 = m03;
-        this.m10 = m10;
-        this.m11 = m11;
-        this.m12 = m12;
-        this.m13 = m13;
-        this.m20 = m20;
-        this.m21 = m21;
-        this.m22 = m22;
-        this.m23 = m23;
-        this.m30 = m30;
-        this.m31 = m31;
-        this.m32 = m32;
-        this.m33 = m33;
+        this.m00 = m00;    this.m01 = m01;    this.m02 = m02;    this.m03 = m03;
+        this.m10 = m10;    this.m11 = m11;    this.m12 = m12;    this.m13 = m13;
+        this.m20 = m20;    this.m21 = m21;    this.m22 = m22;    this.m23 = m23;
+        this.m30 = m30;    this.m31 = m31;    this.m32 = m32;    this.m33 = m33;
     }
 
     /**
@@ -134,6 +122,9 @@ public final class Matrix4 extends Matri
      *
      * @param elements Elements of the matrix. Column indices vary fastest.
      * @throws IllegalArgumentException If the given array does not have the expected length.
+     *
+     * @see #setElements(double[])
+     * @see Matrices#create(int, int, double[])
      */
     public Matrix4(final double[] elements) throws IllegalArgumentException {
         setElements(elements);
@@ -147,7 +138,7 @@ public final class Matrix4 extends Matri
      * @param matrix The matrix to copy.
      * @throws IllegalArgumentException if the given matrix is not of the expected size.
      */
-    public Matrix4(final Matrix matrix) throws IllegalArgumentException {
+    Matrix4(final Matrix matrix) throws IllegalArgumentException {
         for (int j=0; j<SIZE; j++) {
             for (int i=0; i<SIZE; i++) {
                 setElement(j,i, matrix.getElement(j,i));
@@ -155,6 +146,24 @@ public final class Matrix4 extends Matri
         }
     }
 
+    /**
+     * Casts or copies the given matrix to a {@code Matrix4} implementation. If the given {@code matrix}
+     * is already an instance of {@code Matrix4}, then it is returned unchanged. Otherwise this method
+     * verifies the matrix size, then copies all elements in a new {@code Matrix4} object.
+     *
+     * @param  matrix The matrix to cast or copy, or {@code null}.
+     * @return The matrix argument if it can be safely casted (including {@code null} argument),
+     *         or a copy of the given matrix otherwise.
+     * @throws MismatchedMatrixSizeException If the size of the given matrix is not {@value #SIZE}×{@value #SIZE}.
+     */
+    public static Matrix4 castOrCopy(final Matrix matrix) throws MismatchedMatrixSizeException {
+        if (matrix == null || matrix instanceof Matrix4) {
+            return (Matrix4) matrix;
+        }
+        ensureSizeMatch(SIZE, matrix);
+        return new Matrix4(matrix);
+    }
+
     /*
      * The 'final' modifier in following method declarations is redundant with the 'final' modifier
      * in this class declaration, but we keep them as a reminder of which methods should stay final
@@ -260,12 +269,21 @@ public final class Matrix4 extends Matri
      */
     @Override
     public final double[] getElements() {
-        return new double[] {
-            m00, m01, m02, m03,
-            m10, m11, m12, m13,
-            m20, m21, m22, m23,
-            m30, m31, m32, m33
-        };
+        final double[] elements = new double[SIZE*SIZE];
+        getElements(elements);
+        return elements;
+    }
+
+    /**
+     * Copies the matrix elements in the given flat array.
+     * The array length shall be at least 16, may also be 32.
+     */
+    @Override
+    final void getElements(final double[] elements) {
+        elements[ 0] = m00;    elements[ 1] = m01;    elements[ 2] = m02;    elements[ 3] = m03;
+        elements[ 4] = m10;    elements[ 5] = m11;    elements[ 6] = m12;    elements[ 7] = m13;
+        elements[ 8] = m20;    elements[ 9] = m21;    elements[10] = m22;    elements[11] = m23;
+        elements[12] = m30;    elements[13] = m31;    elements[14] = m32;    elements[15] = m33;
     }
 
     /**
@@ -275,22 +293,10 @@ public final class Matrix4 extends Matri
     @Override
     public final void setElements(final double[] elements) {
         ensureLengthMatch(SIZE*SIZE, elements);
-        m00 = elements[ 0];
-        m01 = elements[ 1];
-        m02 = elements[ 2];
-        m03 = elements[ 3];
-        m10 = elements[ 4];
-        m11 = elements[ 5];
-        m12 = elements[ 6];
-        m13 = elements[ 7];
-        m20 = elements[ 8];
-        m21 = elements[ 9];
-        m22 = elements[10];
-        m23 = elements[11];
-        m30 = elements[12];
-        m31 = elements[13];
-        m32 = elements[14];
-        m33 = elements[15];
+        m00 = elements[ 0];    m01 = elements[ 1];    m02 = elements[ 2];    m03 = elements[ 3];
+        m10 = elements[ 4];    m11 = elements[ 5];    m12 = elements[ 6];    m13 = elements[ 7];
+        m20 = elements[ 8];    m21 = elements[ 9];    m22 = elements[10];    m23 = elements[11];
+        m30 = elements[12];    m31 = elements[13];    m32 = elements[14];    m33 = elements[15];
     }
 
     /**
@@ -340,51 +346,6 @@ public final class Matrix4 extends Matri
     }
 
     /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS inverse() throws NoninvertibleMatrixException {
-        return Solver.inverse(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS solve(final Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException {
-        throw new UnsupportedOperationException(); // TODO
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public MatrixSIS multiply(final Matrix matrix) {
-        final int nc = matrix.getNumCol();
-        ensureNumRowMatch(SIZE, matrix, nc);
-        if (nc != SIZE) {
-            return new NonSquareMatrix(this, matrix);
-        }
-        final Matrix4 k = (matrix instanceof Matrix4) ? (Matrix4) matrix : new Matrix4(matrix);
-        return new Matrix4(m00 * k.m00  +  m01 * k.m10  +  m02 * k.m20  +  m03 * k.m30,
-                           m00 * k.m01  +  m01 * k.m11  +  m02 * k.m21  +  m03 * k.m31,
-                           m00 * k.m02  +  m01 * k.m12  +  m02 * k.m22  +  m03 * k.m32,
-                           m00 * k.m03  +  m01 * k.m13  +  m02 * k.m23  +  m03 * k.m33,
-                           m10 * k.m00  +  m11 * k.m10  +  m12 * k.m20  +  m13 * k.m30,
-                           m10 * k.m01  +  m11 * k.m11  +  m12 * k.m21  +  m13 * k.m31,
-                           m10 * k.m02  +  m11 * k.m12  +  m12 * k.m22  +  m13 * k.m32,
-                           m10 * k.m03  +  m11 * k.m13  +  m12 * k.m23  +  m13 * k.m33,
-                           m20 * k.m00  +  m21 * k.m10  +  m22 * k.m20  +  m23 * k.m30,
-                           m20 * k.m01  +  m21 * k.m11  +  m22 * k.m21  +  m23 * k.m31,
-                           m20 * k.m02  +  m21 * k.m12  +  m22 * k.m22  +  m23 * k.m32,
-                           m20 * k.m03  +  m21 * k.m13  +  m22 * k.m23  +  m23 * k.m33,
-                           m30 * k.m00  +  m31 * k.m10  +  m32 * k.m20  +  m33 * k.m30,
-                           m30 * k.m01  +  m31 * k.m11  +  m32 * k.m21  +  m33 * k.m31,
-                           m30 * k.m02  +  m31 * k.m12  +  m32 * k.m22  +  m33 * k.m32,
-                           m30 * k.m03  +  m31 * k.m13  +  m32 * k.m23  +  m33 * k.m33);
-    }
-
-    /**
      * Returns {@code true} if the specified object is of type {@code Matrix4} and
      * all of the data members are equal to the corresponding data members in this matrix.
      *

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java Fri Oct  4 19:03:07 2013
@@ -94,9 +94,8 @@ public abstract class MatrixSIS implemen
     static void ensureNumRowMatch(final int expected, final Matrix matrix, final int numCol) {
         final int actual = matrix.getNumRow();
         if (actual != expected) {
-            final Integer n = numCol;
             throw new MismatchedMatrixSizeException(Errors.format(
-                    Errors.Keys.MismatchedMatrixSize_4, expected, n, actual, n));
+                    Errors.Keys.MismatchedMatrixSize_4, expected, "⒩", actual, numCol));
         }
     }
 
@@ -108,6 +107,24 @@ public abstract class MatrixSIS implemen
     }
 
     /**
+     * Casts or copies the given matrix to a SIS implementation. If {@code matrix} is already
+     * an instance of {@code MatrixSIS}, then it is returned unchanged. Otherwise all elements
+     * are copied in a new {@code MatrixSIS} object.
+     *
+     * @param  matrix The matrix to cast or copy, or {@code null}.
+     * @return The matrix argument if it can be safely casted (including {@code null} argument),
+     *         or a copy of the given matrix otherwise.
+     *
+     * @see Matrices#copy(Matrix)
+     */
+    public static MatrixSIS castOrCopy(final Matrix matrix) {
+        if (matrix == null || matrix instanceof MatrixSIS) {
+            return (MatrixSIS) matrix;
+        }
+        return Matrices.copy(matrix);
+    }
+
+    /**
      * Returns a copy of all matrix elements in a flat, row-major (column indices vary fastest) array.
      * The array length is <code>{@linkplain #getNumRow()} * {@linkplain #getNumCol()}</code>.
      *
@@ -116,6 +133,19 @@ public abstract class MatrixSIS implemen
     public abstract double[] getElements();
 
     /**
+     * Stores all matrix elements in the given flat array. This method does not verify the array length.
+     * All subclasses in this {@code org.apache.sis.referencing.operation.matrix} package override this
+     * method with a more efficient implementation.
+     *
+     * @param dest The destination array. May be longer than necessary (this happen when the caller needs to
+     *             append {@link org.apache.sis.internal.util.DoubleDouble#error} values after the elements).
+     */
+    void getElements(final double[] dest) {
+        final double[] elements = getElements();
+        System.arraycopy(elements, 0, dest, 0, elements.length);
+    }
+
+    /**
      * Sets all matrix elements from a flat, row-major (column indices vary fastest) array.
      * The array length shall be <code>{@linkplain #getNumRow()} * {@linkplain #getNumCol()}</code>.
      *
@@ -186,7 +216,15 @@ public abstract class MatrixSIS implemen
      * @throws MismatchedMatrixSizeException if the number of rows in the given matrix is not equals to the
      *         number of columns in this matrix.
      */
-    public abstract MatrixSIS multiply(Matrix matrix) throws MismatchedMatrixSizeException;
+    public MatrixSIS multiply(final Matrix matrix) throws MismatchedMatrixSizeException {
+        final int numRow = getNumRow();
+        final int numCol = getNumCol();
+        final int nc = matrix.getNumCol();
+        ensureNumRowMatch(numCol, matrix, nc);
+        final GeneralMatrix result = GeneralMatrix.createExtendedPrecision(numRow, nc);
+        result.setToProduct(this, matrix);
+        return result;
+    }
 
     /**
      * Returns the value of <var>U</var> which solves {@code this} × <var>U</var> = {@code matrix}.
@@ -199,7 +237,9 @@ public abstract class MatrixSIS implemen
      *         to the number of columns in this matrix.
      * @throws NoninvertibleMatrixException if this matrix is not invertible.
      */
-    public abstract MatrixSIS solve(Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException;
+    public MatrixSIS solve(final Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException {
+        return Solver.solve(this, matrix);
+    }
 
     /**
      * Returns the inverse of this matrix.
@@ -209,7 +249,9 @@ public abstract class MatrixSIS implemen
      *
      * @see java.awt.geom.AffineTransform#createInverse()
      */
-    public abstract MatrixSIS inverse() throws NoninvertibleMatrixException;
+    public MatrixSIS inverse() throws NoninvertibleMatrixException {
+        return Solver.inverse(this);
+    }
 
     /**
      * Compares the given matrices for equality, using the given absolute tolerance threshold.

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java?rev=1529261&r1=1529260&r2=1529261&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java [UTF-8] Fri Oct  4 19:03:07 2013
@@ -44,9 +44,10 @@ final class NonSquareMatrix extends Gene
      * @param numCol Number of columns.
      * @param setToIdentity {@code true} for initializing the matrix to the identity matrix,
      *        or {@code false} for leaving it initialized to zero.
+     * @param precision 1 for normal precision, or 2 for extended precision.
      */
-    NonSquareMatrix(final int numRow, final int numCol, final boolean setToIdentity) {
-        super(numRow, numCol, setToIdentity);
+    NonSquareMatrix(final int numRow, final int numCol, final boolean setToIdentity, final int precision) {
+        super(numRow, numCol, setToIdentity, precision);
     }
 
     /**
@@ -79,39 +80,23 @@ final class NonSquareMatrix extends Gene
     }
 
     /**
-     * Initializes this matrix to the product of the given matrices.
-     * This constructor shall be invoked only when the result is known to be a non-square matrix.
-     */
-    NonSquareMatrix(final Matrix A, final Matrix B) {
-        super(A.getNumRow(), B.getNumCol(), false);
-        final int numRow = this.numRow; // Protection against accidental changes.
-        final int numCol = this.numCol;
-        final int common = A.getNumCol();
-        ensureNumRowMatch(common, B, numCol);
-        int offset = 0;
-        for (int j=0; j<numRow; j++) {
-            for (int i=0; i<numCol; i++) {
-                double sum = 0;
-                for (int k=0; k<common; k++) {
-                    sum += A.getElement(j, k) * B.getElement(k, i);
-                }
-                elements[offset++] = sum;
-            }
-        }
-    }
-
-    /**
      * Sets the value of this matrix to its transpose.
      */
     @Override
     public void transpose() {
         final short numRow = this.numRow; // Protection against accidental changes before we are done.
         final short numCol = this.numCol;
+        final int   errors = indexOfErrors(numRow, numCol, elements); // Where error values start, or 0 if none.
         final double[] copy = elements.clone();
         int k = 0;
         for (int j=0; j<numRow; j++) {
             for (int i=0; i<numCol; i++) {
-                elements[i*numRow + j] = copy[k++];
+                final int t = i*numRow + j;
+                elements[t] = copy[k];
+                if (errors != 0) {
+                    elements[t + errors] = copy[k + errors];
+                }
+                k++;
             }
         }
         this.numRow = numCol;



Mime
View raw message