sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1755413 - in /sis/branches/JDK8: core/sis-utility/src/main/java/org/apache/sis/math/ core/sis-utility/src/test/java/org/apache/sis/math/ storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/
Date Sat, 06 Aug 2016 23:33:54 GMT
Author: desruisseaux
Date: Sat Aug  6 23:33:54 2016
New Revision: 1755413

URL: http://svn.apache.org/viewvc?rev=1755413&view=rev
Log:
Initial support of Vector of unsigned integers.

Modified:
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Type.java

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java?rev=1755413&r1=1755412&r2=1755413&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java [UTF-8] Sat Aug  6 23:33:54 2016
@@ -17,219 +17,64 @@
 package org.apache.sis.math;
 
 import java.io.Serializable;
-import java.lang.reflect.Array;
-import org.apache.sis.util.Classes;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.collection.CheckedContainer;
 
 
 /**
- * A vector backed by an array. This class does not copy the array, so changes in the underlying
- * array is reflected in this vector and vis-versa. The backing array is typically an array of a
- * primitive type, but array of wrappers are also accepted.
+ * A vector backed by an array of a primitive type. This class does not copy the array,
+ * so changes in the underlying array is reflected in this vector and vis-versa.
  *
  * @author  Martin Desruisseaux (MPO, Geomatys)
  * @since   0.8
  * @version 0.8
  * @module
  */
-final class ArrayVector extends Vector implements Serializable {
-    /**
-     * For cross-version compatibility.
-     */
+abstract class ArrayVector<E extends Number> extends Vector implements CheckedContainer<E>, Serializable {
+    /** For cross-version compatibility. */
     private static final long serialVersionUID = 3496467575389288163L;
 
-    /**
-     * The backing array. This is typically an array of a primitive type,
-     * but can also be an array of wrappers.
-     */
-    private final Object array;
-
-    /**
-     * Creates a new vector for the given array.
-     */
-    ArrayVector(final Object array) {
-        this.array = array;
-    }
-
-    /**
-     * Returns the type of elements in the backing array.
-     * This method returns alway the wrapper type, as documented in the parent class.
-     */
-    @Override
-    public Class<? extends Number> getElementType() {
-        return Numbers.primitiveToWrapper(array.getClass().getComponentType()).asSubclass(Number.class);
-    }
-
-    /**
-     * Returns the length of the backing array.
-     */
-    @Override
-    public int size() {
-        return Array.getLength(array);
-    }
-
-    /**
-     * Returns {@code true} if the value at the given index is {@code NaN}. The default implementation
-     * returns {@code true} if {@code get(index)} returned {@code null} or {@link Double#NaN}. However
-     * subclasses will typically provide more efficient implementations. For example vectors of integer
-     * type return {@code false} unconditionally.
-     *
-     * @param  index the index in the [0…{@linkplain #size size}-1] range.
-     * @return {@code true} if the value at the given index is {@code NaN}.
-     * @throws IndexOutOfBoundsException if the given index is out of bounds.
-     */
-    @Override
-    public boolean isNaN(final int index) throws IndexOutOfBoundsException {
-        final Number n = get(index);
-        return (n == null) || java.lang.Double.isNaN(n.doubleValue());
-    }
+    /** For sub-classes constructor. */
+    ArrayVector() {}
 
-    /**
-     * Returns the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
-     * @throws ClassCastException if the component type can not be converted to a
-     *         {@code double} by an identity or widening conversion.
-     */
-    @Override
-    public double doubleValue(final int index) throws ArrayIndexOutOfBoundsException, ClassCastException {
-        try {
-            return Array.getDouble(array, index);
-        } catch (IllegalArgumentException cause) {
-            throw canNotConvert(double.class, cause);
-        }
+    /** Default implementation for the convenience of direct sub-types. */
+    @Override public boolean isUnsigned() {
+        return false;
     }
 
-    /**
-     * Returns the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
-     * @throws ClassCastException if the component type can not be converted to a
-     *         {@code float} by an identity or widening conversion.
-     */
-    @Override
-    public float floatValue(final int index) throws ArrayIndexOutOfBoundsException, ClassCastException {
-        try {
-            return Array.getFloat(array, index);
-        } catch (IllegalArgumentException cause) {
-            throw canNotConvert(float.class, cause);
-        }
-    }
-
-    /**
-     * Returns the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
-     * @throws ClassCastException if the component type can not be converted to a
-     *         {@code long} by an identity or widening conversion.
-     */
-    @Override
-    public long longValue(final int index) throws ArrayIndexOutOfBoundsException, ClassCastException {
-        try {
-            return Array.getLong(array, index);
-        } catch (IllegalArgumentException cause) {
-            throw canNotConvert(long.class, cause);
-        }
-    }
-
-    /**
-     * Returns the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
-     * @throws ClassCastException if the component type can not be converted to an
-     *         {@code int} by an identity or widening conversion.
-     */
-    @Override
-    public int intValue(final int index) throws ArrayIndexOutOfBoundsException, ClassCastException {
-        try {
-            return Array.getInt(array, index);
-        } catch (IllegalArgumentException cause) {
-            throw canNotConvert(int.class, cause);
-        }
-    }
-
-    /**
-     * Returns the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
-     * @throws ClassCastException if the component type can not be converted to a
-     *         {@code short} by an identity or widening conversion.
-     */
-    @Override
-    public short shortValue(final int index) throws ArrayIndexOutOfBoundsException, ClassCastException {
-        try {
-            return Array.getShort(array, index);
-        } catch (IllegalArgumentException cause) {
-            throw canNotConvert(short.class, cause);
-        }
-    }
-
-    /**
-     * Returns the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
-     * @throws ClassCastException if the component type can not be converted to a
-     *         {@code byte} by an identity or widening conversion.
-     */
-    @Override
-    public byte byteValue(final int index) throws ArrayIndexOutOfBoundsException, ClassCastException {
-        try {
-            return Array.getByte(array, index);
-        } catch (IllegalArgumentException cause) {
-            throw canNotConvert(byte.class, cause);
-        }
-    }
+    /** Default implementation for the convenience of wrapper of integer types. */
+    @Override public boolean    isNaN(int index) {return false;}
+    @Override public long   longValue(int index) {throw canNotConvert(long .class);}
+    @Override public int     intValue(int index) {throw canNotConvert(int  .class);}
+    @Override public short shortValue(int index) {throw canNotConvert(short.class);}
+    @Override public byte   byteValue(int index) {throw canNotConvert(byte .class);}
 
     /**
      * Returns the exception to be thrown when the component type in the backing array can
      * not be converted to the requested type through an identity or widening conversion.
      */
-    private ClassCastException canNotConvert(final Class<?> target, final IllegalArgumentException cause) {
-        final ClassCastException exception = new ClassCastException(Errors.format(
-                Errors.Keys.CanNotConvertFromType_2, array.getClass().getComponentType(), target));
-        exception.initCause(cause);
-        return exception;
+    private ClassCastException canNotConvert(final Class<?> target) {
+        return new ClassCastException(Errors.format(Errors.Keys.CanNotConvertFromType_2,
+                Numbers.wrapperToPrimitive(getElementType()), target));
     }
 
     /**
-     * Returns the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
+     * Verifies that a value of the given type can be casted to the expected type.
+     * The expected type must be one of the {@link Numbers} constants.
      */
-    @Override
-    public Number get(final int index) throws ArrayIndexOutOfBoundsException {
-        return (Number) Array.get(array, index);
-    }
-
-    /**
-     * Sets the value at the given index.
-     *
-     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
-     * @throws ArrayStoreException if the backing array can not store the given object.
-     */
-    @Override
-    public Number set(final int index, final Number value)
-            throws ArrayIndexOutOfBoundsException, ArrayStoreException
-    {
-        final Number old = (Number) Array.get(array, index);
-        try {
-            Array.set(array, index, value);
-        } catch (IllegalArgumentException cause) {
-            throw (ArrayStoreException) new ArrayStoreException(Errors.format(Errors.Keys.CanNotConvertFromType_2,
-                    Classes.getClass(value), array.getClass().getComponentType())).initCause(cause);
+    final void verifyType(final Class<? extends Number> type, final byte expected) {
+        final byte t = Numbers.getEnumConstant(type);
+        if (t < Numbers.BYTE || t > expected) {
+            throw new ArrayStoreException(Errors.format(Errors.Keys.CanNotConvertFromType_2,
+                type, Numbers.wrapperToPrimitive(getElementType())));
         }
-        return old;
     }
 
-
-
-
     /**
-     * A vector backed by an array of type {@code double[]}. This class does not copy the
-     * array, so changes in the underlying array is reflected in this vector and vis-versa.
+     * A vector backed by an array of type {@code double[]}.
      */
-    static final class Double extends Vector implements Serializable {
+    static final class Double extends ArrayVector<java.lang.Double> {
         /** For cross-version compatibility. */
         private static final long serialVersionUID = -2900375382498345812L;
 
@@ -252,12 +97,12 @@ final class ArrayVector extends Vector i
         }
 
         /** Returns {@code true} if the value at the given index is {@code NaN}. */
-        @Override public boolean isNaN(final int index) throws ArrayIndexOutOfBoundsException {
+        @Override public boolean isNaN(final int index) {
             return java.lang.Double.isNaN(array[index]);
         }
 
         /** Returns the value at the given index. */
-        @Override public double doubleValue(final int index) throws ArrayIndexOutOfBoundsException {
+        @Override public double doubleValue(final int index) {
             return array[index];
         }
 
@@ -266,59 +111,34 @@ final class ArrayVector extends Vector i
          * result of the cast is not completely wrong (at worst we get zero of infinity values
          * if the magnitude of the {@code double} value was too small or too large).
          */
-        @Override public float floatValue(int index) throws ArrayIndexOutOfBoundsException {
+        @Override public float floatValue(int index) {
             return (float) array[index];
         }
 
-        /** Can not cast safely to integer values. */
-        @Override public long   longValue(int index) throws ClassCastException {throw canNotConvert(long .class);}
-        @Override public int     intValue(int index) throws ClassCastException {throw canNotConvert(int  .class);}
-        @Override public short shortValue(int index) throws ClassCastException {throw canNotConvert(short.class);}
-        @Override public byte   byteValue(int index) throws ClassCastException {throw canNotConvert(byte .class);}
-
-        /**
-         * Returns the exception to be thrown when the component type in the backing array can
-         * not be converted to the requested type through an identity or widening conversion.
-         */
-        private static ClassCastException canNotConvert(final Class<?> target) {
-            return new ClassCastException(Errors.format(
-                    Errors.Keys.CanNotConvertFromType_2, double.class, target));
-        }
-
         /** Returns the value at the given index. */
-        @Override public java.lang.Double get(final int index) throws ArrayIndexOutOfBoundsException {
+        @Override public Number get(final int index) {
             return array[index];
         }
 
         /** Sets the value at the given index. */
-        @Override public java.lang.Double set(final int index, final Number value) throws ArrayIndexOutOfBoundsException {
+        @Override public Number set(final int index, final Number value) {
             final double old = array[index];
             array[index] = value.doubleValue();
             return old;
         }
     }
 
-
-
-
     /**
-     * A vector backed by an array of type {@code float[]}. This class does not copy the
-     * array, so changes in the underlying array is reflected in this vector and vis-versa.
+     * A vector backed by an array of type {@code float[]}.
      */
-    static final class Float extends Vector implements Serializable {
-        /**
-         * For cross-version compatibility.
-         */
+    static final class Float extends ArrayVector<java.lang.Float> {
+        /** For cross-version compatibility. */
         private static final long serialVersionUID = 5395284704294981455L;
 
-        /**
-         * The backing array.
-         */
+        /** The backing array. */
         private final float[] array;
 
-        /**
-         * Creates a new vector for the given array.
-         */
+        /** Creates a new vector for the given array. */
         Float(final float[] array) {
             this.array = array;
         }
@@ -334,45 +154,272 @@ final class ArrayVector extends Vector i
         }
 
         /** Returns {@code true} if the value at the given index is {@code NaN}. */
-        @Override public boolean isNaN(final int index) throws ArrayIndexOutOfBoundsException {
+        @Override public boolean isNaN(final int index) {
             return java.lang.Float.isNaN(array[index]);
         }
 
         /** Returns the value at the given index. */
-        @Override public double doubleValue(final int index) throws ArrayIndexOutOfBoundsException {
-            return array[index];
+        @Override public double doubleValue(int index) {return array[index];}
+        @Override public float   floatValue(int index) {return array[index];}
+        @Override public Number         get(int index) {return array[index];}
+
+        /** Sets the value at the given index. */
+        @Override public Number set(final int index, final Number value) {
+            final float old = array[index];
+            array[index] = value.floatValue();
+            return old;
         }
+    }
 
-        /** Returns the value at the given index. */
-        @Override public float floatValue(int index) throws ArrayIndexOutOfBoundsException {
-            return array[index];
+    /**
+     * A vector backed by an array of type {@code long[]}.
+     */
+    static class Long extends ArrayVector<java.lang.Long> {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = 338413429037224587L;
+
+        /** The backing array. */
+        private final long[] array;
+
+        /** Creates a new vector for the given array. */
+        Long(final long[] array) {
+            this.array = array;
         }
 
-        /** Can not cast safely to integer values. */
-        @Override public long   longValue(int index) throws ClassCastException {throw canNotConvert(long .class);}
-        @Override public int     intValue(int index) throws ClassCastException {throw canNotConvert(int  .class);}
-        @Override public short shortValue(int index) throws ClassCastException {throw canNotConvert(short.class);}
-        @Override public byte   byteValue(int index) throws ClassCastException {throw canNotConvert(byte .class);}
+        /** Returns the type of elements in the backing array. */
+        @Override public final Class<java.lang.Long> getElementType() {
+            return java.lang.Long.class;
+        }
 
-        /**
-         * Returns the exception to be thrown when the component type in the backing array can
-         * not be converted to the requested type through an identity or widening conversion.
-         */
-        private static ClassCastException canNotConvert(final Class<?> target) {
-            return new ClassCastException(Errors.format(
-                    Errors.Keys.CanNotConvertFromType_2, float.class, target));
+        @Override public final int     size()          {return array.length;}
+        @Override public double doubleValue(int index) {return array[index];}
+        @Override public float   floatValue(int index) {return array[index];}
+        @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];
+            array[index] = value.longValue();
+            return old;
         }
+    }
 
-        /** Returns the value at the given index. */
-        @Override public java.lang.Float get(final int index) throws ArrayIndexOutOfBoundsException {
-            return array[index];
+    /**
+     * A vector backed by an array of type {@code int[]}.
+     */
+    static class Integer extends ArrayVector<java.lang.Integer> {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = -1292641147544275801L;
+
+        /** The backing array. */
+        private final int[] array;
+
+        /** Creates a new vector for the given array. */
+        Integer(final int[] array) {
+            this.array = array;
         }
 
-        /** Sets the value at the given index. */
-        @Override public java.lang.Float set(final int index, final Number value) throws ArrayIndexOutOfBoundsException {
-            final float old = array[index];
-            array[index] = value.floatValue();
+        /** Returns the type of elements in the backing array. */
+        @Override public final Class<java.lang.Integer> getElementType() {
+            return java.lang.Integer.class;
+        }
+
+        @Override public final int     size()          {return array.length;}
+        @Override public double doubleValue(int index) {return array[index];}
+        @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 final Number   set(int index, final Number value) {
+            verifyType(value.getClass(), Numbers.INTEGER);
+            final int old = array[index];
+            array[index] = value.intValue();
             return old;
         }
     }
+
+    /**
+     * A vector backed by an array of type {@code short[]}.
+     */
+    static class Short extends ArrayVector<java.lang.Short> {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = -126825963332296000L;
+
+        /** The backing array. */
+        private final short[] array;
+
+        /** Creates a new vector for the given array. */
+        Short(final short[] array) {
+            this.array = array;
+        }
+
+        /** Returns the type of elements in the backing array. */
+        @Override public final Class<java.lang.Short> getElementType() {
+            return java.lang.Short.class;
+        }
+
+        @Override public final int     size()          {return array.length;}
+        @Override public double doubleValue(int index) {return array[index];}
+        @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 short   shortValue(int index) {return array[index];}
+        @Override public final Number   get(int index) {return shortValue(index);}
+        @Override public final Number   set(int index, final Number value) {
+            verifyType(value.getClass(), Numbers.SHORT);
+            final short old = array[index];
+            array[index] = value.shortValue();
+            return old;
+        }
+    }
+
+    /**
+     * A vector backed by an array of type {@code byte[]}.
+     */
+    static class Byte extends ArrayVector<java.lang.Byte> {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = 7933568876180528548L;
+
+        /** The backing array. */
+        private final byte[] array;
+
+        /** Creates a new vector for the given array. */
+        Byte(final byte[] array) {
+            this.array = array;
+        }
+
+        /** Returns the type of elements in the backing array. */
+        @Override public final Class<java.lang.Byte> getElementType() {
+            return java.lang.Byte.class;
+        }
+
+        @Override public final int     size()          {return array.length;}
+        @Override public double doubleValue(int index) {return array[index];}
+        @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 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 final Number   set(int index, final Number value) {
+            verifyType(value.getClass(), Numbers.BYTE);
+            final byte old = array[index];
+            array[index] = value.byteValue();
+            return old;
+        }
+    }
+
+    /**
+     * A vector backed by an array of type {@code long[]} to be interpreted as unsigned values.
+     */
+    static final class UnsignedLong extends Long {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = 712968674526282882L;
+
+        /** Creates a new vector for the given array. */
+        UnsignedLong(final long[] array) {
+            super(array);
+        }
+
+        /** Declares this vector as unsigned. */
+        @Override public boolean isUnsigned() {return true;}
+
+        /** Returns the unsigned long as a {@code double} value. */
+        @Override public double doubleValue(final int index) {
+            final long value = super.longValue(index);
+            if (value >= 0) {
+                return value;
+            }
+            // This hack is inefficient, but should be rarely needed.
+            return java.lang.Double.parseDouble(java.lang.Long.toUnsignedString(value));
+        }
+
+        /** Returns the unsigned long as a {@code float} value. */
+        @Override public float floatValue(final int index) {
+            final long value = super.longValue(index);
+            if (value >= 0) {
+                return value;
+            }
+            // This hack is inefficient, but should be rarely needed.
+            return java.lang.Float.parseFloat(java.lang.Long.toUnsignedString(value));
+        }
+
+        /** Returns the unsigned long as a {@code long} value, if possible. */
+        @Override public long longValue(final int index) {
+            final long value = super.longValue(index);
+            if (value >= 0) return value;
+            throw new ArithmeticException();
+        }
+    }
+
+    /**
+     * A vector backed by an array of type {@code int[]} to be interpreted as unsigned values.
+     */
+    static final class UnsignedInteger extends Integer {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = 8420585724189054050L;
+
+        /** Creates a new vector for the given array. */
+        UnsignedInteger(final int[] array) {
+            super(array);
+        }
+
+        /** Declares this vector as unsigned. */
+        @Override public boolean isUnsigned()          {return true;}
+        @Override public double doubleValue(int index) {return longValue(index);}
+        @Override public float   floatValue(int index) {return longValue(index);}
+        @Override public long     longValue(int index) {return java.lang.Integer.toUnsignedLong(super.intValue(index));}
+        @Override public int       intValue(int index) {
+            final int value = super.intValue(index);
+            if (value >= 0) return value;
+            throw new ArithmeticException();
+        }
+    }
+
+    /**
+     * A vector backed by an array of type {@code short[]} to be interpreted as unsigned values.
+     */
+    static final class UnsignedShort extends Short {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = 8219060080494444776L;
+
+        UnsignedShort(final short[] array) {
+            super(array);
+        }
+
+        @Override public boolean isUnsigned()          {return true;}
+        @Override public double doubleValue(int index) {return intValue(index);}
+        @Override public float   floatValue(int index) {return intValue(index);}
+        @Override public long     longValue(int index) {return java.lang.Short.toUnsignedLong(super.shortValue(index));}
+        @Override public int       intValue(int index) {return java.lang.Short.toUnsignedInt (super.shortValue(index));}
+        @Override public short   shortValue(int index) {
+            final short value = super.shortValue(index);
+            if (value >= 0) return value;
+            throw new ArithmeticException();
+        }
+    }
+
+    /**
+     * A vector backed by an array of type {@code byte[]} to be interpreted as unsigned values.
+     */
+    static final class UnsignedByte extends Byte {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = -2150064612523948331L;
+
+        UnsignedByte(final byte[] array) {
+            super(array);
+        }
+
+        @Override public boolean isUnsigned()          {return true;}
+        @Override public double doubleValue(int index) {return intValue(index);}
+        @Override public float   floatValue(int index) {return intValue(index);}
+        @Override public long     longValue(int index) {return java.lang.Byte.toUnsignedLong (super.byteValue(index));}
+        @Override public int       intValue(int index) {return java.lang.Byte.toUnsignedInt  (super.byteValue(index));}
+        @Override public short   shortValue(int index) {return (short) intValue(index);}
+        @Override public byte     byteValue(int index) {
+            final byte value = super.byteValue(index);
+            if (value >= 0) return value;
+            throw new ArithmeticException();
+        }
+    }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java?rev=1755413&r1=1755412&r2=1755413&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java [UTF-8] Sat Aug  6 23:33:54 2016
@@ -65,6 +65,14 @@ final class ConcatenatedVector extends V
     }
 
     /**
+     * Returns {@code true} only if both vectors are unsigned.
+     */
+    @Override
+    public boolean isUnsigned() {
+        return first.isUnsigned() && second.isUnsigned();
+    }
+
+    /**
      * Returns the length of this vector.
      */
     @Override

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java?rev=1755413&r1=1755412&r2=1755413&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java [UTF-8] Sat Aug  6 23:33:54 2016
@@ -83,20 +83,28 @@ final class SequenceVector extends Vecto
     }
 
     /**
-     * Returns the vector size.
+     * Returns the type of elements.
      */
     @Override
-    public int size() {
-        return length;
+    public Class<? extends Number> getElementType() {
+        // Float is the smallest type capable to hold NaN.
+        return (type != null) ? type : Float.class;
     }
 
     /**
-     * Returns the type of elements.
+     * {@code SequenceVector} values are always interpreted as signed values.
      */
     @Override
-    public Class<? extends Number> getElementType() {
-        // Float is the smallest type capable to hold NaN.
-        return (type != null) ? type : Float.class;
+    public boolean isUnsigned() {
+        return false;
+    }
+
+    /**
+     * Returns the vector size.
+     */
+    @Override
+    public int size() {
+        return length;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java?rev=1755413&r1=1755412&r2=1755413&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java [UTF-8] Sat Aug  6 23:33:54 2016
@@ -20,7 +20,6 @@ import java.io.Serializable;
 import java.util.Arrays;
 import java.util.AbstractList;
 import java.util.RandomAccess;
-import org.apache.sis.util.Numbers;
 import org.apache.sis.util.resources.Errors;
 
 import static org.apache.sis.util.ArgumentChecks.ensureValidIndex;
@@ -32,10 +31,9 @@ import static org.apache.sis.util.Argume
  * Often the two above-cited cases are used together, for example in a time series where:
  *
  * <ul>
- *   <li><var>x</var>[<var>i</var>] is a linear function of <var>i</var>
+ *   <li><var>x[i]</var> is a linear function of <var>i</var>
  *       (e.g. the sampling time of measurements performed at a fixed time interval)</li>
- *   <li><var>y</var>[<var>i</var>] is the measurement of a phenomenon at time
- *       <var>x</var>[<var>i</var>].</li>
+ *   <li><var>y[i]</var> is the measurement of a phenomenon at time <var>x[i]</var>.</li>
  * </ul>
  *
  * Instances of {@code Vector} are created by calls to the {@link #create(Object)} static method.
@@ -49,6 +47,21 @@ import static org.apache.sis.util.Argume
  *     Vector v = Vector.create(array).subList(lower, upper)
  * }
  *
+ * <div class="note"><b>Note:</b>
+ * the above functionalities look like similar functionalities provided by {@link java.nio.ByteBuffer}
+ * in standard Java, but they actually serve different purposes. The {@code ByteBuffer} getter methods
+ * (for example {@code getShort(int)}, {@code getLong(int)}, <i>etc.</i>) allow to decode a sequence of
+ * bytes in a way determined by the type of the value to decode (2 bytes for a {@code short}, 8 bytes
+ * for a {@code long}, <i>etc.</i>) – the type of the stored value must be known before to read it.
+ * By contrast, this {@code Vector} class is used in situations where <em>the decoding has already been done</em>
+ * by the code that <em>create</em> a {@code Vector} object, but the data type may not be known
+ * by the code that will <em>use</em> the {@code Vector} object.
+ * For example a method performing a numerical calculation may want to see the data as {@code double} values
+ * without concern about whether the data were really stored as {@code double} or as {@code float} values.</div>
+ *
+ * The methods that are most often used after {@code Vector} creation are {@link #size()} and
+ * {@link #doubleValue(int)} or {@link #intValue(int)}.
+ *
  * @author  Martin Desruisseaux (MPO, Geomatys)
  * @since   0.8
  * @version 0.8
@@ -60,37 +73,59 @@ public abstract class Vector extends Abs
      *
      * <ul>
      *   <li>An array of a primitive type, like {@code float[]}.</li>
-     *   <li>An array of a wrapper type, like <code>{@linkplain Float}[]</code>.</li>
      *   <li>A {@code Vector}, in which case it is returned unchanged.</li>
      *   <li>The {@code null} value, in which case {@code null} is returned.</li>
      * </ul>
      *
-     * The argument is not cloned. Consequently changes in the underlying array are reflected
-     * in this vector, and vis-versa.
+     * The given argument is not cloned.
+     * Consequently changes in the underlying array are reflected in this vector, and vis-versa.
      *
-     * @param  array  the object to wrap in a vector, or {@code null}.
+     * @param  array       the object to wrap in a vector, or {@code null}.
+     * @param  isUnsigned  {@code true} if integer types should be interpreted as unsigned integers.
+     *         This argument is ignored if the given array is not a {@code byte[]}, {@code short[]},
+     *         {@code int[]} or {@code long[]} array.
      * @return the given object wrapped in a vector, or {@code null} if the argument was {@code null}.
      * @throws IllegalArgumentException if the type of the given object is not recognized by the method.
      */
-    public static Vector create(final Object array) throws IllegalArgumentException {
+    public static Vector create(final Object array, final boolean isUnsigned) throws IllegalArgumentException {
         if (array instanceof double[]) {
             return new ArrayVector.Double((double[]) array);
         }
         if (array instanceof float[]) {
             return new ArrayVector.Float((float[]) array);
         }
-        if (array == null || array instanceof Vector) {
-            return (Vector) array;
+        if (array instanceof long[]) {
+            if (isUnsigned) {
+                return new ArrayVector.UnsignedLong((long[]) array);
+            } else {
+                return new ArrayVector.Long((long[]) array);
+            }
+        }
+        if (array instanceof int[]) {
+            if (isUnsigned) {
+                return new ArrayVector.UnsignedInteger((int[]) array);
+            } else {
+                return new ArrayVector.Integer((int[]) array);
+            }
+        }
+        if (array instanceof short[]) {
+            if (isUnsigned) {
+                return new ArrayVector.UnsignedShort((short[]) array);
+            } else {
+                return new ArrayVector.Short((short[]) array);
+            }
         }
-        final Class<?> type = array.getClass();
-        Class<?> component = type.getComponentType();
-        if (component != null) {
-            component = Numbers.primitiveToWrapper(component);
-            if (Number.class.isAssignableFrom(component)) {
-                return new ArrayVector(array);
+        if (array instanceof byte[]) {
+            if (isUnsigned) {
+                return new ArrayVector.UnsignedByte((byte[]) array);
+            } else {
+                return new ArrayVector.Byte((byte[]) array);
             }
         }
-        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterType_2, "array", type));
+        if (array == null || array instanceof Vector) {
+            return (Vector) array;
+        }
+        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterType_2, "array", array.getClass()));
     }
 
     /**
@@ -119,14 +154,6 @@ public abstract class Vector extends Abs
     }
 
     /**
-     * Returns the number of elements in this vector.
-     *
-     * @return the number of elements in this vector.
-     */
-    @Override
-    public abstract int size();
-
-    /**
      * Returns the type of elements in this vector. If this vector is backed by an array of a primitive type,
      * then this method returns the <em>wrapper</em> class, not the primitive type. For example if this vector
      * is backed by an array of type {@code float[]}, then this method returns {@code Float.class},
@@ -137,6 +164,23 @@ public abstract class Vector extends Abs
     public abstract Class<? extends Number> getElementType();
 
     /**
+     * Returns {@code true} if integer values shall be interpreted as unsigned values.
+     * Java has no primitive type for unsigned integers, but {@code Vector} implementations
+     * can simulate them by applying the necessary bit masks.
+     *
+     * @return {@code true} if the integer values shall be interpreted as unsigned values.
+     */
+    public abstract boolean isUnsigned();
+
+    /**
+     * Returns the number of elements in this vector.
+     *
+     * @return the number of elements in this vector.
+     */
+    @Override
+    public abstract int size();
+
+    /**
      * Returns {@code true} if the value at the given index is {@code NaN}.
      *
      * @param  index the index in the [0 … {@linkplain #size size}-1] range.
@@ -262,6 +306,7 @@ public abstract class Vector extends Abs
      * Otherwise returns {@code this}. If this method is overridden, it should be
      * together with the {@link #toBacking(int[])} method.
      */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     Vector backingVector() {
         return this;
     }
@@ -380,6 +425,7 @@ public abstract class Vector extends Abs
      * @throws IndexOutOfBoundsException if {@code first} or {@code first + step*(length-1)}
      *         is outside the [0 … {@linkplain #size size}-1] range.
      */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public Vector subList(final int first, final int step, final int length) throws IndexOutOfBoundsException {
         if (step == 1 && first == 0 && length == size()) {
             return this;
@@ -402,6 +448,7 @@ public abstract class Vector extends Abs
      * @param  toAppend the vector to concatenate at the end of this vector.
      * @return the concatenation of this vector with the given vector.
      */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public Vector concatenate(final Vector toAppend) {
         if (toAppend.isEmpty()) {
             return this;
@@ -460,6 +507,11 @@ public abstract class Vector extends Abs
             return Vector.this.getElementType();
         }
 
+        /** Returns whether the type should be interpreted as an unsigned integer type. */
+        @Override public boolean isUnsigned() {
+            return Vector.this.isUnsigned();
+        }
+
         /** Returns the length of this view. */
         @Override public int size() {
             return index.length;
@@ -614,6 +666,11 @@ public abstract class Vector extends Abs
             return Vector.this.getElementType();
         }
 
+        /** Returns whether the type should be interpreted as an unsigned integer type. */
+        @Override public boolean isUnsigned() {
+            return Vector.this.isUnsigned();
+        }
+
         /** Returns the length of this subvector. */
         @Override public int size() {
             return length;

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java?rev=1755413&r1=1755412&r2=1755413&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/VectorTest.java [UTF-8] Sat Aug  6 23:33:54 2016
@@ -64,9 +64,9 @@ public final strictfp class VectorTest e
         for (int i=0; i<array.length; i++) {
             array[i] = (short) ((i + 100) * 10);
         }
-        Vector vector = Vector.create(array);
+        Vector vector = Vector.create(array, false);
         assertTrue(vector instanceof ArrayVector);
-        assertSame(vector, Vector.create(vector));
+        assertSame(vector, Vector.create(vector, false));
         assertEquals(array.length, vector.size());
         assertEquals(Short.class, vector.getElementType());
         /*
@@ -126,9 +126,9 @@ public final strictfp class VectorTest e
         for (int i=0; i<array.length; i++) {
             array[i] = (i + 100) * 10;
         }
-        Vector vector = Vector.create(array);
+        Vector vector = Vector.create(array, false);
         assertTrue(vector instanceof ArrayVector.Float);
-        assertSame(vector, Vector.create(vector));
+        assertSame(vector, Vector.create(vector, false));
         assertEquals(array.length, vector.size());
         assertEquals(Float.class, vector.getElementType());
         /*
@@ -149,9 +149,9 @@ public final strictfp class VectorTest e
         for (int i=0; i<array.length; i++) {
             array[i] = (i + 100) * 10;
         }
-        Vector vector = Vector.create(array);
+        Vector vector = Vector.create(array, false);
         assertTrue(vector instanceof ArrayVector.Double);
-        assertSame(vector, Vector.create(vector));
+        assertSame(vector, Vector.create(vector, false));
         assertEquals(array.length, vector.size());
         assertEquals(Double.class, vector.getElementType());
         /*
@@ -170,7 +170,8 @@ public final strictfp class VectorTest e
     public void testReverse() {
         final double[] array    = {2, 3, 8};
         final double[] expected = {8, 3, 2};
-        assertEquals(Vector.create(expected), Vector.create(array).reverse());
+        assertEquals(Vector.create(expected, false),
+                     Vector.create(array, false).reverse());
     }
 
     /**
@@ -186,8 +187,8 @@ public final strictfp class VectorTest e
         for (int i=0; i<extra.length; i++) {
             extra[i] = (i + 40) * 10;
         }
-        Vector v1 = Vector.create(array);
-        Vector v2 = Vector.create(extra);
+        Vector v1 = Vector.create(array, false);
+        Vector v2 = Vector.create(extra, false);
         Vector v3 = v1.concatenate(v2);
         assertEquals("Length of V3 should be the sum of V1 and V2 length.", 60, v3.size());
         assertEquals("Component type should be the widest of V1 and V2.", Float.class, v3.getElementType());

Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Type.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Type.java?rev=1755413&r1=1755412&r2=1755413&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Type.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Type.java [UTF-8] Sat Aug  6 23:33:54 2016
@@ -46,7 +46,7 @@ enum Type {
      *   <li>TIFF code: 7</li>
      * </ul>
      */
-    UNDEFINED(7, Byte.BYTES),
+    UNDEFINED(7, Byte.BYTES, false),
 
     /**
      * An 8-bits signed (twos-complement) integer.
@@ -55,7 +55,7 @@ enum Type {
      *   <li>TIFF code: 6</li>
      * </ul>
      */
-    BYTE(6, Byte.BYTES) {
+    BYTE(6, Byte.BYTES, false) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             return input.readByte();
@@ -73,11 +73,15 @@ enum Type {
      *   <li>TIFF code: 1</li>
      * </ul>
      */
-    UBYTE(1, Byte.BYTES) {
+    UBYTE(1, Byte.BYTES, true) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             return input.readUnsignedByte();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readBytes(count);
+        }
     },
 
     /**
@@ -87,7 +91,7 @@ enum Type {
      *   <li>TIFF code: 8</li>
      * </ul>
      */
-    SHORT(8, Short.BYTES) {
+    SHORT(8, Short.BYTES, false) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             return input.readShort();
@@ -105,11 +109,15 @@ enum Type {
      *   <li>TIFF code: 3</li>
      * </ul>
      */
-    USHORT(3, Short.BYTES) {
+    USHORT(3, Short.BYTES, true) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             return input.readUnsignedShort();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readShorts(count);
+        }
     },
 
     /**
@@ -119,7 +127,7 @@ enum Type {
      *   <li>TIFF code: 9</li>
      * </ul>
      */
-    INT(9, Integer.BYTES) {
+    INT(9, Integer.BYTES, false) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             return input.readInt();
@@ -137,11 +145,15 @@ enum Type {
      *   <li>TIFF code: 4</li>
      * </ul>
      */
-    UINT(4, Integer.BYTES) {
+    UINT(4, Integer.BYTES, true) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             return input.readUnsignedInt();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readInts(count);
+        }
     },
 
     /**
@@ -150,7 +162,7 @@ enum Type {
      *   <li>TIFF code: 17</li>
      * </ul>
      */
-    LONG(17, Long.BYTES) {
+    LONG(17, Long.BYTES, false) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             return input.readLong();
@@ -167,7 +179,7 @@ enum Type {
      *   <li>TIFF code: 16</li>
      * </ul>
      */
-    ULONG(16, Long.BYTES) {
+    ULONG(16, Long.BYTES, true) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             final long value = input.readLong();
@@ -185,6 +197,10 @@ enum Type {
             }
             return Double.parseDouble(Long.toUnsignedString(value));    // Inefficient but should be very rare.
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readLongs(count);
+        }
     },
 
     /**
@@ -194,7 +210,7 @@ enum Type {
      *   <li>TIFF code: 11</li>
      * </ul>
      */
-    FLOAT(11, Float.BYTES) {
+    FLOAT(11, Float.BYTES, false) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             final float value = input.readFloat();
@@ -222,7 +238,7 @@ enum Type {
      *   <li>TIFF code: 12</li>
      * </ul>
      */
-    DOUBLE(12, Double.BYTES) {
+    DOUBLE(12, Double.BYTES, false) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             final double value = input.readDouble();
@@ -250,7 +266,7 @@ enum Type {
      *   <li>TIFF code: 10</li>
      * </ul>
      */
-    RATIONAL(10, (2*Integer.BYTES)) {
+    RATIONAL(10, (2*Integer.BYTES), false) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             final int numerator   = input.readInt();
@@ -281,7 +297,7 @@ enum Type {
      *   <li>TIFF code: 5</li>
      * </ul>
      */
-    URATIONAL(5, (2*Integer.BYTES)) {
+    URATIONAL(5, (2*Integer.BYTES), true) {
         @Override long readLong(final ChannelDataInput input, final long count) throws IOException {
             ensureSingleton(count);
             final long numerator   = input.readUnsignedInt();
@@ -314,7 +330,7 @@ enum Type {
      *   <li>TIFF code: 2</li>
      * </ul>
      */
-    ASCII(2, Byte.BYTES) {
+    ASCII(2, Byte.BYTES, false) {
         @Override String[] readString(final ChannelDataInput input, final long length, final Charset charset) throws IOException {
             final byte[] chars = input.readBytes(Math.toIntExact(length));
             String[] lines = new String[1];                     // We will usually have exactly one string.
@@ -354,11 +370,17 @@ enum Type {
     final int size;
 
     /**
+     * Whether this type is an unsigned integer.
+     */
+    final boolean isUnsigned;
+
+    /**
      * Creates a new enumeration
      */
-    private Type(final int code, final int size) {
+    private Type(final int code, final int size, final boolean isUnsigned) {
         this.code = code;
         this.size = size;
+        this.isUnsigned = isUnsigned;
     }
 
     /**
@@ -517,6 +539,6 @@ enum Type {
      * @throws UnsupportedOperationException if this type is {@link #UNDEFINED}.
      */
     final Vector readVector(final ChannelDataInput input, final long count) throws IOException {
-        return Vector.create(readArray(input, Math.toIntExact(count)));
+        return Vector.create(readArray(input, Math.toIntExact(count)), isUnsigned);
     }
 }



Mime
View raw message