sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1755122 - in /sis/branches/JDK8: core/sis-utility/src/main/java/org/apache/sis/math/ storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/
Date Wed, 03 Aug 2016 22:34:50 GMT
Author: desruisseaux
Date: Wed Aug  3 22:34:50 2016
New Revision: 1755122

URL: http://svn.apache.org/viewvc?rev=1755122&view=rev
Log:
Initial port of Vector classes (as wrapper around array of Java primitive type) as helper classes for reading GeoTIFF data.
Test classes will need to be ported later, as well as other wrappers for unsigned bytes, shorts, ints and longs.

Added:
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java   (with props)
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java   (with props)
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java   (with props)
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/package-info.java
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Type.java

Added: 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=1755122&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java (added)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java [UTF-8] Wed Aug  3 22:34:50 2016
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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;
+
+
+/**
+ * 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.
+ *
+ * @author  Martin Desruisseaux (MPO, Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+final class ArrayVector extends Vector implements 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());
+    }
+
+    /**
+     * 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);
+        }
+    }
+
+    /**
+     * 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);
+        }
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Returns the value at the given index.
+     *
+     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
+     */
+    @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);
+        }
+        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.
+     */
+    static final class Double extends Vector implements Serializable {
+        /** For cross-version compatibility. */
+        private static final long serialVersionUID = -2900375382498345812L;
+
+        /** The backing array. */
+        private final double[] array;
+
+        /** Creates a new vector for the given array. */
+        Double(final double[] array) {
+            this.array = array;
+        }
+
+        /** Returns the type of elements in the backing array. */
+        @Override public Class<java.lang.Double> getElementType() {
+            return java.lang.Double.class;
+        }
+
+        /** Returns the length of the backing array. */
+        @Override public int size() {
+            return array.length;
+        }
+
+        /** Returns {@code true} if the value at the given index is {@code NaN}. */
+        @Override public boolean isNaN(final int index) throws ArrayIndexOutOfBoundsException {
+            return java.lang.Double.isNaN(array[index]);
+        }
+
+        /** Returns the value at the given index. */
+        @Override public double doubleValue(final int index) throws ArrayIndexOutOfBoundsException {
+            return array[index];
+        }
+
+        /**
+         * Returns the value casted as a {@code float}, since we may loose precision but the
+         * 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 {
+            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 {
+            return array[index];
+        }
+
+        /** Sets the value at the given index. */
+        @Override public java.lang.Double set(final int index, final Number value) throws ArrayIndexOutOfBoundsException {
+            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.
+     */
+    static final class Float extends Vector implements Serializable {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = 5395284704294981455L;
+
+        /**
+         * The backing array.
+         */
+        private final float[] array;
+
+        /**
+         * Creates a new vector for the given array.
+         */
+        Float(final float[] array) {
+            this.array = array;
+        }
+
+        /** Returns the type of elements in the backing array. */
+        @Override public Class<java.lang.Float> getElementType() {
+            return java.lang.Float.class;
+        }
+
+        /** Returns the length of the backing array. */
+        @Override public int size() {
+            return array.length;
+        }
+
+        /** Returns {@code true} if the value at the given index is {@code NaN}. */
+        @Override public boolean isNaN(final int index) throws ArrayIndexOutOfBoundsException {
+            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];
+        }
+
+        /** Returns the value at the given index. */
+        @Override public float floatValue(int index) throws ArrayIndexOutOfBoundsException {
+            return 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, float.class, target));
+        }
+
+        /** Returns the value at the given index. */
+        @Override public java.lang.Float get(final int index) throws ArrayIndexOutOfBoundsException {
+            return array[index];
+        }
+
+        /** 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();
+            return old;
+        }
+    }
+}

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ArrayVector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: 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=1755122&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java (added)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java [UTF-8] Wed Aug  3 22:34:50 2016
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.math;
+
+import java.io.Serializable;
+import org.apache.sis.util.Numbers;
+
+
+/**
+ * A vector which is the concatenation of two other vectors.
+ *
+ * @author  Martin Desruisseaux (MPO, Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+final class ConcatenatedVector extends Vector implements Serializable {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 4639375525939012394L;
+
+    /**
+     * The vectors to concatenate.
+     */
+    private final Vector first, second;
+
+    /**
+     * The length of the first vector.
+     */
+    private final int limit;
+
+    /**
+     * Creates a concatenated vector.
+     *
+     * @param first  the vector for the lower indices.
+     * @param second the vector for the higher indices.
+     */
+    public ConcatenatedVector(final Vector first, final Vector second) {
+        this.first  = first;
+        this.second = second;
+        this.limit  = first.size();
+    }
+
+    /**
+     * Returns widest type of the two vectors.
+     */
+    @Override
+    public Class<? extends Number> getElementType() {
+        return Numbers.widestClass(first.getElementType(), second.getElementType());
+    }
+
+    /**
+     * Returns the length of this vector.
+     */
+    @Override
+    public int size() {
+        return limit + second.size();
+    }
+
+    /**
+     * Returns {@code true} if the value at the given index is {@code NaN}.
+     */
+    @Override
+    public boolean isNaN(int index) throws IndexOutOfBoundsException {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.isNaN(index);
+    }
+
+    /**
+     * Returns the value at the given index.
+     */
+    @Override
+    public double doubleValue(int index) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.doubleValue(index);
+    }
+
+    /**
+     * Returns the value at the given index.
+     */
+    @Override
+    public float floatValue(int index) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.floatValue(index);
+    }
+
+    /**
+     * Returns the value at the given index.
+     */
+    @Override
+    public long longValue(int index) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.longValue(index);
+    }
+
+    /**
+     * Returns the value at the given index.
+     */
+    @Override
+    public int intValue(int index) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.intValue(index);
+    }
+
+    /**
+     * Returns the value at the given index.
+     */
+    @Override
+    public short shortValue(int index) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.shortValue(index);
+    }
+
+    /**
+     * Returns the value at the given index.
+     */
+    @Override
+    public byte byteValue(int index) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.byteValue(index);
+    }
+
+    /**
+     * Returns the value at the given index.
+     *
+     * @throws ArrayIndexOutOfBoundsException if the given index is out of bounds.
+     */
+    @Override
+    public Number get(int index) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.get(index);
+    }
+
+    /**
+     * Sets the value at the given index.
+     */
+    @Override
+    public Number set(int index, final Number value) {
+        final Vector v;
+        if (index < limit) {
+            v = first;
+        } else {
+            v = second;
+            index -= limit;
+        }
+        return v.set(index, value);
+    }
+
+    /**
+     * Delegates to the backing vectors if possible.
+     */
+    @Override
+    Vector createSubList(final int first, final int step, final int length) {
+        if (first >= limit) {
+            return second.subList(first - limit, step, length);
+        }
+        if (first + step*length <= limit) {
+            return this.first.subList(first, step, length);
+        }
+        return super.createSubList(first, step, length);
+    }
+
+    /**
+     * Delegates to the backing vectors since there is a chance that they overloaded
+     * their {@code concatenate} method with a more effective implementation.
+     */
+    @Override
+    Vector createConcatenate(final Vector toAppend) {
+        return first.concatenate(second.concatenate(toAppend));
+    }
+}

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/ConcatenatedVector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: 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=1755122&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java (added)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java [UTF-8] Wed Aug  3 22:34:50 2016
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.math;
+
+import java.io.Serializable;
+import org.apache.sis.util.resources.Errors;
+
+import static org.apache.sis.util.Numbers.*;
+import static org.apache.sis.util.ArgumentChecks.ensureValidIndex;
+
+
+/**
+ * A vector which is a sequence of numbers.
+ *
+ * @author  Martin Desruisseaux (MPO, Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+final class SequenceVector extends Vector implements Serializable {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 7980737287789566091L;
+
+    /**
+     * The element type, or {@code null} if values are NaN.
+     */
+    private final Class<? extends Number> type;
+
+    /**
+     * The value at index 0.
+     */
+    private final double first;
+
+    /**
+     * The difference between the values at two adjacent indexes.
+     */
+    private final double increment;
+
+    /**
+     * The length of this vector.
+     */
+    private final int length;
+
+    /**
+     * Creates a sequence of numbers in a given range of values using the given increment.
+     *
+     * @param first     The first value, inclusive.
+     * @param increment The difference between the values at two adjacent indexes.
+     * @param length    The length of the vector.
+     */
+    public SequenceVector(final double first, final double increment, final int length) {
+        if (length < 0) {
+            throw new IllegalArgumentException(Errors.format(
+                    Errors.Keys.IllegalArgumentValue_2, "length", length));
+        }
+        this.first     = first;
+        this.increment = increment;
+        this.length    = length;
+        if (Double.isNaN(first) || Double.isNaN(increment)) {
+            type = null;
+        } else {
+            Class<? extends Number> t = narrowestClass(first);
+            t = widestClass(t, narrowestClass(first + increment));
+            t = widestClass(t, narrowestClass(first + increment*(length-1)));
+            type = t;
+        }
+    }
+
+    /**
+     * Returns the vector size.
+     */
+    @Override
+    public int size() {
+        return length;
+    }
+
+    /**
+     * Returns the type of elements.
+     */
+    @Override
+    public Class<? extends Number> getElementType() {
+        // Float is the smallest type capable to hold NaN.
+        return (type != null) ? type : Float.class;
+    }
+
+    /**
+     * Returns {@code true} if this vector returns {@code NaN} values.
+     */
+    @Override
+    public boolean isNaN(final int index) {
+        return type == null;
+    }
+
+    /**
+     * Computes the value at the given index.
+     */
+    @Override
+    public double doubleValue(final int index) throws IndexOutOfBoundsException {
+        ensureValidIndex(length, index);
+        return first + increment*index;
+    }
+
+    /**
+     * Computes the value at the given index.
+     */
+    @Override
+    public float floatValue(final int index) throws IndexOutOfBoundsException {
+        return (float) doubleValue(index);
+    }
+
+    /**
+     * Computes the value at the given index.
+     */
+    @Override
+    public long longValue(final int index) throws IndexOutOfBoundsException {
+        return Math.round(doubleValue(index));
+    }
+
+    /**
+     * Computes the value at the given index.
+     */
+    @Override
+    public int intValue(final int index) throws IndexOutOfBoundsException {
+        return (int) longValue(index);
+    }
+
+    /**
+     * Computes the value at the given index.
+     */
+    @Override
+    public short shortValue(final int index) throws IndexOutOfBoundsException {
+        return (short) longValue(index);
+    }
+
+    /**
+     * Computes the value at the given index.
+     */
+    @Override
+    public byte byteValue(final int index) throws IndexOutOfBoundsException {
+        return (byte) longValue(index);
+    }
+
+    /**
+     * Computes the value at the given index.
+     */
+    @Override
+    public Number get(final int index) throws IndexOutOfBoundsException {
+        return doubleValue(index);
+    }
+
+    /**
+     * Unsupported operation since this vector is not modifiable.
+     */
+    @Override
+    public Number set(final int index, final Number value) {
+        throw new UnsupportedOperationException(Errors.format(Errors.Keys.UnmodifiableObject_1, "Vector"));
+    }
+
+    /**
+     * Creates a new sequence.
+     */
+    @Override
+    Vector createSubList(final int first, final int step, final int length) {
+        return new SequenceVector(doubleValue(first), increment*step, length);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/SequenceVector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: 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=1755122&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java (added)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java [UTF-8] Wed Aug  3 22:34:50 2016
@@ -0,0 +1,685 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.math;
+
+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;
+
+
+/**
+ * A vector of real numbers. An instance of {@code Vector} can be a wrapper around an array of Java primitive type
+ * (typically {@code float[]} or {@code double[]}), or it may be a function calculating values on the fly.
+ * 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>
+ *       (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>
+ * </ul>
+ *
+ * Instances of {@code Vector} are created by calls to the {@link #create(Object)} static method.
+ * The supplied array is not cloned – changes to the primitive array are reflected in the vector,
+ * and vis-versa.
+ *
+ * Vectors can be created over a subrange of an array, provides a view of the elements in reverse
+ * order, <i>etc</i>. The example below creates a view over a subrange:
+ *
+ * {@preformat java
+ *     Vector v = Vector.create(array).subList(lower, upper)
+ * }
+ *
+ * @author  Martin Desruisseaux (MPO, Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+public abstract class Vector extends AbstractList<Number> implements RandomAccess {
+    /**
+     * Wraps the given object in a vector. The argument should be one of the following:
+     *
+     * <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.
+     *
+     * @param  array  the object to wrap in a vector, or {@code null}.
+     * @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 {
+        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;
+        }
+        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);
+            }
+        }
+        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterType_2, "array", type));
+    }
+
+    /**
+     * Creates a sequence of numbers in a given range of values using the given increment.
+     * The range of values will be {@code first} inclusive to {@code (first + increment*length)} exclusive.
+     * Note that the value given by the {@code first} argument is equivalent to a "lowest" or "minimum" value
+     * only if the given increment is positive.
+     *
+     * <p>The {@linkplain #getElementType() element type} will be the smallest type that can be used
+     * for storing every values. For example it will be {@code Byte.class} for the range [100:1:120]
+     * but will be {@code Double.class} for the range [0:0.1:1].</p>
+     *
+     * @param  first      the first value, inclusive.
+     * @param  increment  the difference between the values at two adjacent indexes.
+     * @param  length     the length of the desired vector.
+     * @return the given sequence as a vector.
+     */
+    public static Vector createSequence(final double first, final double increment, final int length) {
+        return new SequenceVector(first, increment, length);
+    }
+
+    /**
+     * For subclasses constructor.
+     */
+    protected Vector() {
+    }
+
+    /**
+     * 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},
+     * not {@link Float#TYPE}.
+     *
+     * @return the type of elements in this vector.
+     */
+    public abstract Class<? extends Number> getElementType();
+
+    /**
+     * 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.
+     * @return {@code true} if the value at the given index is {@code NaN}.
+     * @throws IndexOutOfBoundsException if the given index is out of bounds.
+     */
+    public abstract boolean isNaN(final int index) throws IndexOutOfBoundsException;
+
+    /**
+     * Returns the value at the given index as a {@code double}.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @return the value at the given index.
+     * @throws IndexOutOfBoundsException 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.
+     */
+    public abstract double doubleValue(final int index) throws IndexOutOfBoundsException, ClassCastException;
+
+    /**
+     * Returns the value at the given index as a {@code float}.
+     * If this vector uses internally a wider type like {@code double}, then this method may
+     * cast the value or throw an exception at implementation choice. The general guidelines
+     * are:
+     *
+     * <ul>
+     *   <li>If the value is read from a primitive array of a wider type (typically through a
+     *       vector created by {@link #create(Object)}, throw an exception because we assume
+     *       that the data provider thinks that the extra precision is needed.</li>
+     *   <li>If the value is the result of a computation (typically through a vector created
+     *       by {@link #createSequence}), cast the value because the calculation accuracy is
+     *       often unknown to the vector - and not necessarily its job.</li>
+     * </ul>
+     *
+     * For safety users should either call {@link #doubleValue(int)} in all cases, or call this
+     * methods only if the type returned by {@link #getElementType()} has been verified.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @return the value at the given index.
+     * @throws IndexOutOfBoundsException 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.
+     */
+    public abstract float floatValue(final int index) throws IndexOutOfBoundsException, ClassCastException;
+
+    /**
+     * Returns the value at the given index as a {@code long}.
+     * If this vector uses internally a wider type, then this method may cast the value
+     * or throw an exception according the same guidelines than {@link #floatValue(int)}.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @return the value at the given index.
+     * @throws IndexOutOfBoundsException 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.
+     */
+    public abstract long longValue(final int index) throws IndexOutOfBoundsException, ClassCastException;
+
+    /**
+     * Returns the value at the given index as an {@code int}.
+     * If this vector uses internally a wider type, then this method may cast the value
+     * or throw an exception according the same guidelines than {@link #floatValue(int)}.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @return the value at the given index.
+     * @throws IndexOutOfBoundsException 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.
+     */
+    public abstract int intValue(final int index) throws IndexOutOfBoundsException, ClassCastException;
+
+    /**
+     * Returns the value at the given index as a {@code short}.
+     * If this vector uses internally a wider type, then this method may cast the value
+     * or throw an exception according the same guidelines than {@link #floatValue(int)}.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @return the value at the given index.
+     * @throws IndexOutOfBoundsException 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.
+     */
+    public abstract short shortValue(final int index) throws IndexOutOfBoundsException, ClassCastException;
+
+    /**
+     * Returns the value at the given index as a {@code byte}.
+     * If this vector uses internally a wider type, then this method may cast the value
+     * or throw an exception according the same guidelines than {@link #floatValue(int)}.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @return the value at the given index.
+     * @throws IndexOutOfBoundsException 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.
+     */
+    public abstract byte byteValue(final int index) throws IndexOutOfBoundsException, ClassCastException;
+
+    /**
+     * Returns the number at the given index, or {@code null} if none.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @return the value at the given index.
+     * @throws IndexOutOfBoundsException if the given index is out of bounds.
+     */
+    @Override
+    public abstract Number get(final int index) throws IndexOutOfBoundsException;
+
+    /**
+     * Sets the number at the given index.
+     *
+     * @param  index the index in the [0 … {@linkplain #size size}-1] range.
+     * @param  value the value to set at the given index.
+     * @return the value previously stored at the given index.
+     * @throws IndexOutOfBoundsException if the given index is out of bounds.
+     * @throws ArrayStoreException if the given value can not be stored in this vector.
+     */
+    @Override
+    public abstract Number set(final int index, final Number value)
+            throws IndexOutOfBoundsException, ArrayStoreException;
+
+    /**
+     * If this vector is a view over an other vector, returns the backing vector.
+     * Otherwise returns {@code this}. If this method is overridden, it should be
+     * together with the {@link #toBacking(int[])} method.
+     */
+    Vector backingVector() {
+        return this;
+    }
+
+    /**
+     * Converts an array of indexes used by this vector to the indexes used by the backing vector.
+     * If there is no such backing vector, then returns a clone of the given array.
+     * This method must also check index validity.
+     *
+     * <p>Only subclasses that are views of this vector will override this method.</p>
+     *
+     * @param  index the indexes given by the user.
+     * @return the indexes to use. Must be a new array in order to protect it from user changes.
+     * @throws IndexOutOfBoundsException if at least one index is out of bounds.
+     */
+    int[] toBacking(int[] index) throws IndexOutOfBoundsException {
+        index = index.clone();
+        final int length = size();
+        for (int i : index) {
+            ensureValidIndex(length, i);
+        }
+        return index;
+    }
+
+    /**
+     * Returns a view which contains the values of this vector at the given indexes.
+     * This method does not copy the values, consequently any modification to the
+     * values of this vector will be reflected in the returned view and vis-versa.
+     *
+     * <p>The indexes don't need to be in any particular order. The same index can be repeated
+     * more than once. Thus it is possible to create a vector larger than the original vector.</p>
+     *
+     * @param  index index of the values to be returned.
+     * @return a view of this vector containing values at the given indexes.
+     * @throws IndexOutOfBoundsException if at least one index is out of bounds.
+     */
+    public Vector view(int... index) throws IndexOutOfBoundsException {
+        index = toBacking(index);
+        final int first, step;
+        switch (index.length) {
+            case 0: {
+                first = 0;
+                step  = 1;
+                break;
+            }
+            case 1: {
+                first = index[0];
+                step  = 1;
+                break;
+            }
+            default: {
+                int limit;
+                first = index[0];
+                limit = index[1];
+                step  = limit - first;
+                for (int i=2; i<index.length; i++) {
+                    final int current = index[i];
+                    if (current - limit != step) {
+                        return backingVector().new View(index);
+                    }
+                    limit = current;
+                }
+                break;
+            }
+        }
+        return subList(first, step, index.length);
+    }
+
+    /**
+     * Returns a view which contains the values of this vector in reverse order. This method delegates its work
+     * to <code>{@linkplain #subList(int,int,int) subList}(size-1, -1, {@linkplain #size() size})</code>.
+     * It is declared final in order to force every subclasses to override the later method instead than this one.
+     *
+     * @return the vector values in reverse order.
+     */
+    public final Vector reverse() {
+        final int length = size();
+        return (length != 0) ? subList(length-1, -1, length) : this;
+    }
+
+    /**
+     * Returns a view which contain the values of this vector in the given index range.
+     * The returned view will contain the values from index {@code lower} inclusive to
+     * {@code upper} exclusive.
+     *
+     * <p>This method delegates its work to <code>{@linkplain #subList(int,int,int) subList}(lower,
+     * 1, upper-lower)</code>. It is declared final in order to force every subclasses to override
+     * the later method instead than this one.</p>
+     *
+     * @param  lower index of the first value to be included in the returned view.
+     * @param  upper index after the last value to be included in the returned view.
+     * @return a view of this vector containing values in the given index range.
+     * @throws IndexOutOfBoundsException If an index is outside the [0 … {@linkplain #size size}-1] range.
+     */
+    @Override
+    public final Vector subList(final int lower, final int upper) throws IndexOutOfBoundsException {
+        return subList(lower, 1, upper - lower);
+    }
+
+    /**
+     * Returns a view which contain the values of this vector in a given index range.
+     * The returned view will contain the values from index {@code first} inclusive to
+     * {@code (first + step*length)} exclusive with index incremented by the given {@code step} value,
+     * which can be negative. More specifically the index <var>i</var> in the returned vector will maps
+     * the element at index <code>(first + step*<var>i</var>)</code> in this vector.
+     *
+     * <p>This method does not copy the values. Consequently any modification to the
+     * values of this vector will be reflected in the returned view and vis-versa.</p>
+     *
+     * @param  first  index of the first value to be included in the returned view.
+     * @param  step   the index increment in this vector between two consecutive values
+     *                in the returned vector. Can be positive, zero or negative.
+     * @param  length the length of the vector to be returned. Can not be greater than
+     *                the length of this vector, except if the {@code step} is zero.
+     * @return a view of this vector containing values in the given index range.
+     * @throws IndexOutOfBoundsException if {@code first} or {@code first + step*(length-1)}
+     *         is outside the [0 … {@linkplain #size size}-1] range.
+     */
+    public Vector subList(final int first, final int step, final int length) throws IndexOutOfBoundsException {
+        if (step == 1 && first == 0 && length == size()) {
+            return this;
+        }
+        return createSubList(first, step, length);
+    }
+
+    /**
+     * Implementation of {@link #subList(int,int,int)} to be overridden by subclasses.
+     */
+    Vector createSubList(final int first, final int step, final int length) {
+        return new SubList(first, step, length);
+    }
+
+    /**
+     * Returns the concatenation of this vector with the given one. Indexes in the [0 … {@linkplain #size size}-1]
+     * range will map to this vector, while indexes in the [size … size + toAppend.size] range while map to the
+     * given vector.
+     *
+     * @param  toAppend the vector to concatenate at the end of this vector.
+     * @return the concatenation of this vector with the given vector.
+     */
+    public Vector concatenate(final Vector toAppend) {
+        if (toAppend.isEmpty()) {
+            return this;
+        }
+        if (isEmpty()) {
+            return toAppend;
+        }
+        return createConcatenate(toAppend);
+    }
+
+    /**
+     * Implementation of {@link #concatenate(Vector)} to be overridden by subclasses.
+     */
+    Vector createConcatenate(final Vector toAppend) {
+        return new ConcatenatedVector(this, toAppend);
+    }
+
+    /**
+     * A view over an other vector at pre-selected indexes.
+     */
+    private final class View extends Vector implements Serializable {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = 6574040261355090760L;
+
+        /**
+         * The pre-selected indexes.
+         */
+        private final int[] index;
+
+        /**
+         * Creates a new view over the values at the given indexes. This constructor
+         * does not clone the array; it is caller responsibility to clone it if needed.
+         */
+        public View(int[] index) {
+            this.index = index;
+        }
+
+        /** Returns the backing vector. */
+        @Override Vector backingVector() {
+            return Vector.this;
+        }
+
+        /** Returns the indexes where to look for the value in the enclosing vector. */
+        @Override int[] toBacking(final int[] i) throws IndexOutOfBoundsException {
+            final int[] ni = new int[i.length];
+            for (int j=0; j<ni.length; j++) {
+                ni[j] = index[i[j]];
+            }
+            return ni;
+        }
+
+        /** Returns the type of elements in this vector. */
+        @Override public Class<? extends Number> getElementType() {
+            return Vector.this.getElementType();
+        }
+
+        /** Returns the length of this view. */
+        @Override public int size() {
+            return index.length;
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public boolean isNaN(final int i) {
+            return Vector.this.isNaN(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public double doubleValue(final int i) {
+            return Vector.this.doubleValue(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public float floatValue(final int i) {
+            return Vector.this.floatValue(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public long longValue(final int i) {
+            return Vector.this.longValue(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public int intValue(final int i) {
+            return Vector.this.intValue(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public short shortValue(final int i) {
+            return Vector.this.shortValue(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public byte byteValue(final int i) {
+            return Vector.this.byteValue(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public Number get(final int i) {
+            return Vector.this.get(index[i]);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public Number set(final int i, final Number value) {
+            return Vector.this.set(index[i], value);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override Vector createSubList(int first, final int step, final int length) {
+            ensureValid(first, step, length);
+            final int[] ni = new int[length];
+            if (step == 1) {
+                System.arraycopy(index, first, ni, 0, length);
+            } else for (int j=0; j<length; j++) {
+                ni[j] = index[first];
+                first += step;
+            }
+            return Vector.this.view(ni);
+        }
+
+        /** Concatenates the indexes if possible. */
+        @Override Vector createConcatenate(final Vector toAppend) {
+            if (toAppend instanceof View && toAppend.backingVector() == Vector.this) {
+                final int[] other = ((View) toAppend).index;
+                final int[] c = Arrays.copyOf(index, index.length + other.length);
+                System.arraycopy(other, 0, c, index.length, other.length);
+                return Vector.this.view(c);
+            }
+            return super.createConcatenate(toAppend);
+        }
+    }
+
+    /**
+     * Ensures that the range created from the given parameters is valid.
+     */
+    static void ensureValid(final int first, final int step, final int length) {
+        if (length < 0) {
+            final short key;
+            final Object arg1, arg2;
+            if (step == 1) {
+                key  = Errors.Keys.IllegalRange_2;
+                arg1 = first;
+                arg2 = first + length;
+            } else {
+                key  = Errors.Keys.IllegalArgumentValue_2;
+                arg1 = "range";
+                arg2 = "[" + first + ':' + step + ':' + (first + step*length) + ']';
+            }
+            throw new IllegalArgumentException(Errors.format(key, arg1, arg2));
+        }
+    }
+
+    /**
+     * A view over an other vector in a range of index.
+     */
+    private final class SubList extends Vector implements Serializable {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = 7641036842053528486L;
+
+        /**
+         * Index of the first element in the enclosing vector.
+         */
+        private final int first;
+
+        /**
+         * The index increment. May be negative but not zero.
+         */
+        private final int step;
+
+        /**
+         * The length of this vector.
+         */
+        private final int length;
+
+        /**
+         * Creates a new view over the given range.
+         */
+        protected SubList(final int first, final int step, final int length) {
+            ensureValid(first, step, length);
+            this.first  = first;
+            this.step   = step;
+            this.length = length;
+        }
+
+        /** Returns the backing vector. */
+        @Override Vector backingVector() {
+            return Vector.this;
+        }
+
+        /** Returns the index where to look for the value in the enclosing vector. */
+        private int toBacking(final int index) throws IndexOutOfBoundsException {
+            ensureValidIndex(length, index);
+            return index*step + first;
+        }
+
+        /** Returns the index where to look for the value in the enclosing vector. */
+        @Override int[] toBacking(final int[] index) throws IndexOutOfBoundsException {
+            final int[] ni = new int[index.length];
+            for (int j=0; j<ni.length; j++) {
+                ni[j] = toBacking(index[j]);
+            }
+            return ni;
+        }
+
+        /** Returns the type of elements in this vector. */
+        @Override public Class<? extends Number> getElementType() {
+            return Vector.this.getElementType();
+        }
+
+        /** Returns the length of this subvector. */
+        @Override public int size() {
+            return length;
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public boolean isNaN(final int index) {
+            return Vector.this.isNaN(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public double doubleValue(final int index) {
+            return Vector.this.doubleValue(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public float floatValue(final int index) {
+            return Vector.this.floatValue(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public long longValue(final int index) {
+            return Vector.this.longValue(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public int intValue(final int index) {
+            return Vector.this.intValue(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public short shortValue(final int index) {
+            return Vector.this.shortValue(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public byte byteValue(final int index) {
+            return Vector.this.byteValue(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public Number get(final int index) {
+            return Vector.this.get(toBacking(index));
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override public Number set(final int index, final Number value) {
+            return Vector.this.set(toBacking(index), value);
+        }
+
+        /** Delegates to the enclosing vector. */
+        @Override Vector createSubList(int first, int step, final int length) {
+            first = toBacking(first);
+            step *= this.step;
+            return Vector.this.subList(first, step, length);
+        }
+
+        /** Delegates to the enclosing vector if possible. */
+        @Override Vector createConcatenate(final Vector toAppend) {
+            if (toAppend instanceof SubList && toAppend.backingVector() == Vector.this) {
+                final SubList other = (SubList) toAppend;
+                if (other.step == step && other.first == first + step*length) {
+                    return Vector.this.createSubList(first, step, length + other.length);
+                }
+            }
+            return super.createConcatenate(toAppend);
+        }
+    }
+}

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Vector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/package-info.java?rev=1755122&r1=1755121&r2=1755122&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/package-info.java [UTF-8] Wed Aug  3 22:34:50 2016
@@ -34,7 +34,7 @@
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.8
  * @module
  */
 package org.apache.sis.math;

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=1755122&r1=1755121&r2=1755122&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] Wed Aug  3 22:34:50 2016
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import org.apache.sis.internal.storage.ChannelDataInput;
+import org.apache.sis.math.Vector;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.resources.Errors;
 
@@ -59,6 +60,10 @@ enum Type {
             ensureSingleton(count);
             return input.readByte();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readBytes(count);
+        }
     },
 
     /**
@@ -87,6 +92,10 @@ enum Type {
             ensureSingleton(count);
             return input.readShort();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readShorts(count);
+        }
     },
 
     /**
@@ -115,6 +124,10 @@ enum Type {
             ensureSingleton(count);
             return input.readInt();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readInts(count);
+        }
     },
 
     /**
@@ -142,6 +155,10 @@ enum Type {
             ensureSingleton(count);
             return input.readLong();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readLongs(count);
+        }
     },
 
     /**
@@ -192,6 +209,10 @@ enum Type {
             ensureSingleton(count);
             return input.readFloat();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readFloats(count);
+        }
     },
 
     /**
@@ -216,6 +237,10 @@ enum Type {
             ensureSingleton(count);
             return input.readDouble();
         }
+
+        @Override Object readArray(final ChannelDataInput input, final int count) throws IOException {
+            return input.readDoubles(count);
+        }
     },
 
     /**
@@ -457,11 +482,41 @@ enum Type {
      * @throws ArithmeticException if the given length is too large.
      * @throws UnsupportedOperationException if this type is {@link #UNDEFINED}.
      */
-    String[] readString(ChannelDataInput input, final long length, final Charset charset) throws IOException {
+    String[] readString(final ChannelDataInput input, final long length, final Charset charset) throws IOException {
         final String[] s = new String[Math.toIntExact(length)];
         for (int i=0; i<s.length; i++) {
             s[i] = String.valueOf(readLong(input, 1));
         }
         return s;
     }
+
+    /**
+     * Reads an arbitrary amount of values as a Java array.
+     *
+     * @param  input  the input from where to read the values.
+     * @param  count  the amount of values.
+     * @return the value as a Java array.
+     * @throws IOException if an error occurred while reading the stream.
+     * @throws UnsupportedOperationException if this type is {@link #UNDEFINED}.
+     */
+    Object readArray(ChannelDataInput input, int count) throws IOException {
+        throw new UnsupportedOperationException(name());
+    }
+
+    /**
+     * Reads an arbitrary amount of values as a wrapper around a Java array of primitive type.
+     * This wrapper provide a more convenient way to access array elements than the object
+     * returned by {@link #readArray(ChannelDataInput, int)}.
+     *
+     * @param  input  the input from where to read the values.
+     * @param  count  the amount of values.
+     * @return the value as a wrapper around a Java array of primitive type.
+     * @throws IOException if an error occurred while reading the stream.
+     * @throws ArithmeticException if the given count is too large.
+     * @throws NumberFormatException if the value was stored in ASCII and can not be parsed.
+     * @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)));
+    }
 }



Mime
View raw message