This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 99a1d79f15ba5e8df85264ded7282a3040a4a650
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Aug 18 17:06:46 2022 +0200

    Add a `MatrixSIS.getInteger(j,i)` method returning a `long`.
    This method can be more accurate than `double` type when using 
`GeneralMatrix`.
---
 .../operation/matrix/GeneralMatrix.java            | 28 +++++++++++++++++++++-
 .../referencing/operation/matrix/MatrixSIS.java    | 17 ++++++++++++-
 .../referencing/operation/matrix/package-info.java |  2 +-
 .../operation/matrix/GeneralMatrixTest.java        | 19 ++++++++++++++-
 .../org/apache/sis/internal/util/DoubleDouble.java | 14 +++++++----
 5 files changed, 72 insertions(+), 8 deletions(-)

diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
index ae2ae27bb4..01ed4330df 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
@@ -36,7 +36,7 @@ import 
org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
  * the {@link DoubleDouble#error}.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.3
  *
  * @see Matrices#createDiagonal(int, int)
  *
@@ -262,6 +262,32 @@ class GeneralMatrix extends MatrixSIS implements 
ExtendedPrecisionMatrix {
         }
     }
 
+    /**
+     * Retrieves the value at the specified row and column of this matrix, 
rounded to nearest integer.
+     *
+     * @param  row     the row index, from 0 inclusive to {@link #getNumRow()} 
exclusive.
+     * @param  column  the column index, from 0 inclusive to {@link 
#getNumCol()} exclusive.
+     * @return the current value at the given row and column, rounded to 
nearest integer.
+     *
+     * @see DoubleDouble#longValue()
+     *
+     * @since 1.3
+     */
+    @Override
+    public long getInteger(int row, int column) {
+        if (row >= 0 && row < numRow && column >= 0 && column < numCol) {
+            int i = row * numCol + column;
+            long value = Math.round(elements[i]);
+            i += numRow * numCol;
+            if (i < elements.length) {
+                value += (long) elements[i];        // Really want rounding 
toward zero.
+            }
+            return value;
+        } else {
+            throw indexOutOfBounds(row, column);
+        }
+    }
+
     /**
      * Retrieves the value at the specified row and column of this matrix, 
wrapped in a {@code Number}
      * or a {@link DoubleDouble} depending on available precision.
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
index 316ac2f5e9..cee43acaa2 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
@@ -55,7 +55,7 @@ import org.apache.sis.util.resources.Errors;
  * </ul>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.1
+ * @version 1.3
  *
  * @see Matrices
  *
@@ -163,6 +163,21 @@ public abstract class MatrixSIS implements Matrix, 
LenientComparable, Cloneable,
         setElement(row, column, dd.doubleValue());
     }
 
+    /**
+     * Retrieves the value at the specified row and column of this matrix, 
rounded to nearest integer.
+     * This method may be more accurate than {@link #getElement(int, int)} in 
some implementations
+     * when the value is expected to be an integer (for example in conversions 
of pixel coordinates).
+     *
+     * @param  row     the row index, from 0 inclusive to {@link #getNumRow()} 
exclusive.
+     * @param  column  the column index, from 0 inclusive to {@link 
#getNumCol()} exclusive.
+     * @return the current value at the given row and column, rounded to 
nearest integer.
+     *
+     * @since 1.3
+     */
+    public long getInteger(int row, int column) {
+        return Math.round(getElement(row, column));
+    }
+
     /**
      * Retrieves the value at the specified row and column of this matrix, 
wrapped in a {@code Number}.
      * The {@code Number} type depends on the matrix accuracy.
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/package-info.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/package-info.java
index 23ced6d69d..1cbd737608 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/package-info.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/package-info.java
@@ -69,7 +69,7 @@
  * Like SIS, Vecmath is optimized for small matrices of interest for 2D and 3D 
graphics.</p>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   0.4
  * @module
  */
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/GeneralMatrixTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/GeneralMatrixTest.java
index 8d3d883649..b65a2ed69f 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/GeneralMatrixTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/GeneralMatrixTest.java
@@ -17,6 +17,7 @@
 package org.apache.sis.referencing.operation.matrix;
 
 import java.util.Random;
+import org.apache.sis.internal.util.DoubleDouble;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
@@ -27,7 +28,7 @@ import static org.junit.Assert.*;
  * This class inherits all tests defined in {@link MatrixTestCase}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   0.4
  * @module
  */
@@ -59,6 +60,22 @@ public final strictfp class GeneralMatrixTest extends 
MatrixTestCase {
         assertEquals(GeneralMatrix.class, matrix.getClass());
     }
 
+    /**
+     * Tests {@link GeneralMatrix#getNumber(int, int)} and {@link 
GeneralMatrix#getInteger(int, int)}
+     * using a value which can not be stored accurately in a {@code double} 
type.
+     */
+    @Test
+    public void testExtendedPrecision() {
+        final long value = 1000000000000010000L;
+        assertNotEquals(value, Math.round((double) value));
+        final GeneralMatrix m = new GeneralMatrix(1, 1, false, 2);
+        final DoubleDouble ddval = new DoubleDouble((Long) value);
+        m.setNumber(0, 0, ddval);
+        assertEquals(Long.toString(value), ddval.toString());
+        assertEquals(ddval, m.getNumber (0, 0));
+        assertEquals(value, m.getInteger(0, 0));
+    }
+
     /**
      * Tests {@link GeneralMatrix#getExtendedElements(Matrix, int, int, 
boolean)}.
      * This test verifies that {@code getExtendedElements} can infer default 
error
diff --git 
a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java 
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
index 4b483d600a..b8a5ad407b 100644
--- 
a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
+++ 
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
@@ -56,7 +56,7 @@ import org.apache.sis.math.DecimalFunctions;
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
  *
  * @see <a 
href="https://en.wikipedia.org/wiki/Double-double_%28arithmetic%29#Double-double_arithmetic";>Wikipedia:
 Double-double arithmetic</a>
  *
@@ -220,6 +220,8 @@ public final class DoubleDouble extends Number {
             value = otherValue.doubleValue();
             if (otherValue instanceof DoubleDouble) {
                 error = ((DoubleDouble) otherValue).error;
+            } else if (otherValue instanceof Long) {
+                error = otherValue.longValue() - (long) value;
             } else if (otherValue instanceof BigDecimal) {
                 // Really need new BigDecimal(value) below, not 
BigDecimal.valueOf(value).
                 error = ((BigDecimal) otherValue).subtract(new 
BigDecimal(value), MathContext.DECIMAL64).doubleValue();
@@ -231,8 +233,11 @@ public final class DoubleDouble extends Number {
 
     /**
      * Returns {@code true} if the given value is one of the special cases 
recognized by the
-     * {@link DoubleDouble(Number)} constructor. Those special cases should 
rarely occur, so
-     * we do not complicate the code with optimized code paths.
+     * {@link #DoubleDouble(Number)} constructor. Those special cases should 
rarely occur,
+     * so we do not complicate the code with optimized code paths.
+     *
+     * <p>This method does not test if the given value is already an instance 
of {@code DoubleDouble}.
+     * That verification should be done by the caller.</p>
      *
      * @param  value  the value to test.
      * @return {@code true} if it is worth to convert the given value to a 
{@code DoubleDouble}.
@@ -240,7 +245,8 @@ public final class DoubleDouble extends Number {
      * @since 0.8
      */
     public static boolean shouldConvert(final Number value) {
-        return (value instanceof Fraction) || (value instanceof BigInteger) || 
(value instanceof BigDecimal);
+        return (value instanceof Fraction)   || (value instanceof Long) ||
+               (value instanceof BigInteger) || (value instanceof BigDecimal);
     }
 
     /**

Reply via email to