sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Fix an ArithmeticException when using vector wrapping unsigned short values.
Date Thu, 10 Jan 2019 12:23:06 GMT
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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 1c0463b  Fix an ArithmeticException when using vector wrapping unsigned short values.
1c0463b is described below

commit 1c0463bee5013387fceb90a9984875049784d624
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Jan 10 13:22:11 2019 +0100

    Fix an ArithmeticException when using vector wrapping unsigned short values.
---
 .../main/java/org/apache/sis/math/ArrayVector.java | 72 +++++++++++++++++-----
 .../java/org/apache/sis/math/PackedVector.java     |  2 +-
 .../test/java/org/apache/sis/math/VectorTest.java  | 39 ++++++++++++
 3 files changed, 98 insertions(+), 15 deletions(-)

diff --git a/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java b/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
index 1ea8354..499e01b 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
@@ -27,6 +27,7 @@ import java.nio.DoubleBuffer;
 import java.util.Arrays;
 import java.util.Optional;
 import java.util.function.IntSupplier;
+import org.apache.sis.util.Classes;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.resources.Errors;
@@ -84,7 +85,7 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
         } else if (array instanceof String[]) {
             vec = new ASCII((String[]) array);
         } else {
-            throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentClass_2,
"array", array.getClass()));
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentClass_2,
"array", Classes.getClass(array)));
         }
         return vec;
     }
@@ -181,10 +182,11 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
     }
 
     /**
-     * Verifies that a value of the given type can be casted to the expected type.
+     * Verifies that the given value can be casted to the expected type.
      * The expected type must be one of the {@link Numbers} constants.
      */
-    final void verifyType(final Class<? extends Number> type, final byte expected)
{
+    void verifyType(final Number value, final byte expected) {
+        final Class<? extends Number> type = value.getClass();
         final byte t = Numbers.getEnumConstant(type);
         if (t < Numbers.BYTE || t > expected) {
             throw new ClassCastException(Errors.format(Errors.Keys.CanNotConvertFromType_2,
@@ -498,8 +500,8 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
         @Override public long     longValue(int index) {return array[index];}
         @Override public final Number   get(int index) {return longValue(index);}
         @Override public final Number   set(int index, final Number value) {
-            verifyType(value.getClass(), Numbers.LONG);
-            final long old = array[index];
+            verifyType(value, Numbers.LONG);
+            final Number old = get(index);
             array[index] = value.longValue();
             modCount++;
             return old;
@@ -615,10 +617,10 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
         @Override public float   floatValue(int index) {return array[index];}
         @Override public long     longValue(int index) {return array[index];}
         @Override public int       intValue(int index) {return array[index];}
-        @Override public final Number   get(int index) {return intValue(index);}
+        @Override public Number         get(int index) {return array[index];}
         @Override public final Number   set(int index, final Number value) {
-            verifyType(value.getClass(), Numbers.INTEGER);
-            final int old = array[index];
+            verifyType(value, Numbers.INTEGER);
+            final Number old = get(index);
             array[index] = value.intValue();
             modCount++;
             return old;
@@ -738,10 +740,10 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
         @Override public long     longValue(int index) {return array[index];}
         @Override public int       intValue(int index) {return array[index];}
         @Override public short   shortValue(int index) {return array[index];}
-        @Override public final Number   get(int index) {return shortValue(index);}
+        @Override public Number         get(int index) {return array[index];}
         @Override public final Number   set(int index, final Number value) {
-            verifyType(value.getClass(), Numbers.SHORT);
-            final short old = array[index];
+            verifyType(value, Numbers.SHORT);
+            final Number old = get(index);
             array[index] = value.shortValue();
             modCount++;
             return old;
@@ -836,10 +838,10 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
         @Override public int       intValue(int index) {return array[index];}
         @Override public short   shortValue(int index) {return array[index];}
         @Override public byte     byteValue(int index) {return array[index];}
-        @Override public final Number   get(int index) {return shortValue(index);}
+        @Override public Number         get(int index) {return array[index];}
         @Override public final Number   set(int index, final Number value) {
-            verifyType(value.getClass(), Numbers.BYTE);
-            final byte old = array[index];
+            verifyType(value, Numbers.BYTE);
+            final Number old = get(index);
             array[index] = value.byteValue();
             modCount++;
             return old;
@@ -969,6 +971,20 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
             throw new ArithmeticException();
         }
 
+        /** Uses a larger type if the value exceed integer capacity. */
+        @Override public Number get(int index) {
+            final int value = super.intValue(index);
+            if (value >= 0) return value;
+            return Integer.toUnsignedLong(value);
+        }
+
+        /** Verifies that the given value can be stored as an unsigned integer. */
+        @Override void verifyType(final Number value, byte expected) {
+            final long v = value.longValue();
+            if ((v & ~0xFFFFFFFFL) == 0) expected = Numbers.LONG;
+            super.verifyType(value, expected);
+        }
+
         /** Returns the string representation at the given index. */
         @Override public String stringValue(final int index) {
             return Integer.toUnsignedString(super.intValue(index));
@@ -1011,6 +1027,20 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
             throw new ArithmeticException();
         }
 
+        /** Uses a larger type if the value exceed short integer capacity. */
+        @Override public Number get(int index) {
+            final short value = super.shortValue(index);
+            if (value >= 0) return value;
+            return Short.toUnsignedInt(value);
+        }
+
+        /** Verifies that the given value can be stored as an unsigned integer. */
+        @Override void verifyType(final Number value, byte expected) {
+            final int v = value.intValue();
+            if ((v & ~0xFFFF) == 0) expected = Numbers.INTEGER;
+            super.verifyType(value, expected);
+        }
+
         /** Returns the string representation at the given index. */
         @Override public String stringValue(final int index) {
             return Integer.toString(intValue(index));
@@ -1054,6 +1084,20 @@ abstract class ArrayVector<E extends Number> extends Vector implements
CheckedCo
             throw new ArithmeticException();
         }
 
+        /** Uses a larger type if the value exceed integer capacity. */
+        @Override public Number get(int index) {
+            final byte value = super.byteValue(index);
+            if (value >= 0) return value;
+            return (short) Byte.toUnsignedInt(value);
+        }
+
+        /** Verifies that the given value can be stored as an unsigned integer. */
+        @Override void verifyType(final Number value, byte expected) {
+            final int v = value.intValue();
+            if ((v & ~0xFF) == 0) expected = Numbers.SHORT;
+            super.verifyType(value, expected);
+        }
+
         /** Returns the string representation at the given index. */
         @Override public String stringValue(final int index) {
             return Integer.toString(intValue(index));
diff --git a/core/sis-utility/src/main/java/org/apache/sis/math/PackedVector.java b/core/sis-utility/src/main/java/org/apache/sis/math/PackedVector.java
index 394a178..4688461 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/math/PackedVector.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/math/PackedVector.java
@@ -200,7 +200,7 @@ final class PackedVector extends ArrayVector<Long> {
      */
     @Override
     public Number set(final int index, final Number value) {
-        verifyType(value.getClass(), Numbers.LONG);
+        verifyType(value, Numbers.LONG);
         long v = value.longValue();
         if (v >= offset) {
             v -= offset;
diff --git a/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java b/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java
index 590b977..275ea03 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java
@@ -127,6 +127,45 @@ public final strictfp class VectorTest extends TestCase {
     }
 
     /**
+     * Tests {@link ArrayVector} backed by an array of primitive type handled as unsigned
values.
+     */
+    @Test
+    public void testUnsignedByteArray() {
+        final byte[] array = new byte[100];
+        for (int i=0; i<array.length; i++) {
+            array[i] = (byte) ((i + 3) * 2);
+        }
+        vector = Vector.create(array, true);
+        assertTrue(vector instanceof ArrayVector);
+        assertSame(vector, Vector.create(vector, true));
+        assertEquals(array.length, vector.size());
+        assertEquals(Byte.class, vector.getElementType());
+
+        // Verifies element values.
+        for (int i=0; i<array.length; i++) {
+            final int expected = Byte.toUnsignedInt(array[i]);
+            assertEquals(expected, vector.shortValue (i));
+            assertEquals(expected, vector.intValue   (i));
+            assertEquals(expected, vector.floatValue (i), 0f);
+            assertEquals(expected, vector.doubleValue(i), STRICT);
+        }
+
+        // Tests exception.
+        assertEquals(106, vector.byteValue(50));
+        assertEquals(146, vector.shortValue(70));
+        try {
+            vector.byteValue(70);
+            fail("Expected a ArithmeticException");
+        } catch (ArithmeticException e) {
+            // This is the expected exception.
+        }
+
+        // Test writing.
+        vector.set(70, (short) 200);
+        assertEquals(200, vector.shortValue(70));
+    }
+
+    /**
      * Tests {@link ArrayVector} backed by an array of float type.
      */
     @Test


Mime
View raw message