<commit_before>/*
 * 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 java.util.function.IntSupplier;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.internal.util.Numerics;

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[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[i]</var> is the measurement of a phenomenon at time <var>x[i]</var>.</li>
 * </ul>
 *
 * <div class="section">Instantiation</div>
 * Instances of {@code Vector} are usually created by calls to the {@link #create(Object, boolean)} static method.
 * The supplied array is not cloned – changes to the primitive array are reflected in the vector, and vis-versa.
 * Vectors can be a view over a subsection of the given array, or can provide a view of the elements in reverse order,
 * <i>etc</i>. The example below creates a view over a subsection:
 *
 * {@preformat java
 *     float[] array = new float[100];
 *     Vector v = Vector.create(array, false).subList(20, 40)
 *     // At this point, v.doubleValue(0) is equivalent to (double) array[20].
 * }
 *
 * <div class="section">Usage</div>
 * The methods that are most often used after {@code Vector} creation are {@link #size()} and {@link #doubleValue(int)}
 * or {@link #intValue(int)}. Those methods make abstraction of the underlying data type. For example if the vector is
 * backed by an array of type {@code int[]}, then calls to {@code doubleValue(index)} will:
 *
 * <ul>
 *   <li>Convert the {@code int[index]} value to a {@code double} value.</li>
 *   <li>If {@link #isUnsigned()} is {@code true}, apply the necessary bitmask before conversion.</li>
 * </ul>
 *
 * Widening conversions (for example from {@code short} to {@code long}) are always allowed.
 * Narrowing conversions are allowed if the result can be represented at least approximatively by the target type.
 * For example conversions from {@code double} to {@code float} are always allowed (values that are too large for
 * the {@code float} type are represented by positive of negative infinity), but conversions from {@code long} to
 * {@code short} are allowed only if the value is between {@link Short#MIN_VALUE} and {@link Short#MAX_VALUE} inclusive.
 *
 * <div class="note"><b>Comparison with other API:</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>
 *
 * @author  <NAME> (MPO, Geomatys)
 * @version 0.8
 *
 * @see org.apache.sis.util.collection.IntegerList
 *
 * @since 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>A {@code Number[]} array.</li>
     *   <li>A {@code String[]} array (not recommended, but happen with some file formats).</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 given argument is not cloned.
     * Consequently changes in the underlying array are reflected in this vector, and vis-versa.
     *
     * <div class="section">Unsigned integers</div>
     * Java has no primitive support for unsigned integers. But some file formats use unsigned integers,
     * which can be simulated in Java by the use of bit masks or methods like {@link Integer#toUnsignedLong(int)}.
     * This {@code Vector} class applies automatically those masks (unless otherwise noticed in method Javadoc)
     * if the {@code isUnsigned} argument is {@code true}.
     * That argument applies only to {@code byte[]}, {@code short[]}, {@code int[]} or {@code long[]} arrays
     * and is ignored for all other kind of arrays.
     *
     * @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.
     * @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, final boolean isUnsigned) throws IllegalArgumentException {
        if (array == null) {
            return null;
        }
        if (array.getClass().isArray()) {
            return ArrayVector.newInstance(array, isUnsigned);
        }
        if (array instanceof Vector) {
            return (Vector) array;
        }
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentClass_2, "array", array.getClass()));
    }

    /**
     * Wraps the given {@code float[]} array in a vector that preserve the string representations in base 10.
     * For example the 0.1 {@code float} value casted to {@code double} normally produces 0.10000000149011612
     * because of the way IEEE 754 arithmetic represents numbers (in base 2 instead than base 10). But the
     * vector returned by this method will convert the 0.1 {@code float} value into the 0.1 {@code double} value.
     * Note that despite the appearance, this is <strong>not</strong> more accurate than the normal cast,
     * because base 10 is not more privileged in nature than base 2.
     *
     * <div class="section">When to use</div>
     * This method can be used when there is good reasons to think that the {@code float} numbers were parsed
     * from decimal representations, for example an ASCII file. There is usually no reason to use this method
     * if the values are the result of some numerical computations.
     *
     * @param  array  the object to wrap in a vector, or {@code null}.
     * @return the given array wrapped in a vector, or {@code null} if the argument was {@code null}.
     *
     * @see DecimalFunctions#floatToDouble(float)
     */
    public static Vector createForDecimal(final float[] array) {
        return (array != null) ? new ArrayVector.Decimal(array) : null;
    }

    /**
     * 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 inferred from the type of the given
     * {@code Number} instances. If will typically be {@code Integer.class} for the [100:1:120] range
     * and {@code Double.class} for the [0:0.1:1] range.</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 Number first, final Number increment, final int length) {
        Class<? extends Number> type;
        type = Numbers.widestClass(first, increment);
        type = Numbers.widestClass(type,
               Numbers.narrowestClass(first.doubleValue() + increment.doubleValue() * (length-1)));
        return createSequence(type, first, increment, length);
    }

    /**
     * Creates a sequence of the given type.
     */
    static Vector createSequence(final Class<? extends Number> type, final Number first, final Number increment, final int length) {
        final int t = Numbers.getEnumConstant(type);
        if (t >= Numbers.BYTE && t <= Numbers.LONG) {
            // Use the long type if possible because not all long values can be represented as double.
            return new SequenceVector.Longs(type, first, increment, length);
        } else {
            return new SequenceVector.Doubles(type, first, increment, length);
        }
    }

    /**
     * For subclasses constructor.
     */
    protected Vector() {
    }

    /**
     * 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}.
     *
     * <p>The information returned by this method is only indicative; it is not guaranteed to specify accurately
     * this kind of objects returned by the {@link #get(int)} method. There is various situation where the types
     * may not match:</p>
     *
     * <ul>
     *   <li>If this vector {@linkplan #isUnsigned() is unsigned}, then the values returned by {@code get(int)}<commit_msg>Fix javadoc typo.<commit_after>/*
 * 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 java.util.function.IntSupplier;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.internal.util.Numerics;

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[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[i]</var> is the measurement of a phenomenon at time <var>x[i]</var>.</li>
 * </ul>
 *
 * <div class="section">Instantiation</div>
 * Instances of {@code Vector} are usually created by calls to the {@link #create(Object, boolean)} static method.
 * The supplied array is not cloned – changes to the primitive array are reflected in the vector, and vis-versa.
 * Vectors can be a view over a subsection of the given array, or can provide a view of the elements in reverse order,
 * <i>etc</i>. The example below creates a view over a subsection:
 *
 * {@preformat java
 *     float[] array = new float[100];
 *     Vector v = Vector.create(array, false).subList(20, 40)
 *     // At this point, v.doubleValue(0) is equivalent to (double) array[20].
 * }
 *
 * <div class="section">Usage</div>
 * The methods that are most often used after {@code Vector} creation are {@link #size()} and {@link #doubleValue(int)}
 * or {@link #intValue(int)}. Those methods make abstraction of the underlying data type. For example if the vector is
 * backed by an array of type {@code int[]}, then calls to {@code doubleValue(index)} will:
 *
 * <ul>
 *   <li>Convert the {@code int[index]} value to a {@code double} value.</li>
 *   <li>If {@link #isUnsigned()} is {@code true}, apply the necessary bitmask before conversion.</li>
 * </ul>
 *
 * Widening conversions (for example from {@code short} to {@code long}) are always allowed.
 * Narrowing conversions are allowed if the result can be represented at least approximatively by the target type.
 * For example conversions from {@code double} to {@code float} are always allowed (values that are too large for
 * the {@code float} type are represented by positive of negative infinity), but conversions from {@code long} to
 * {@code short} are allowed only if the value is between {@link Short#MIN_VALUE} and {@link Short#MAX_VALUE} inclusive.
 *
 * <div class="note"><b>Comparison with other API:</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>
 *
 * @author  <NAME> (MPO, Geomatys)
 * @version 0.8
 *
 * @see org.apache.sis.util.collection.IntegerList
 *
 * @since 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>A {@code Number[]} array.</li>
     *   <li>A {@code String[]} array (not recommended, but happen with some file formats).</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 given argument is not cloned.
     * Consequently changes in the underlying array are reflected in this vector, and vis-versa.
     *
     * <div class="section">Unsigned integers</div>
     * Java has no primitive support for unsigned integers. But some file formats use unsigned integers,
     * which can be simulated in Java by the use of bit masks or methods like {@link Integer#toUnsignedLong(int)}.
     * This {@code Vector} class applies automatically those masks (unless otherwise noticed in method Javadoc)
     * if the {@code isUnsigned} argument is {@code true}.
     * That argument applies only to {@code byte[]}, {@code short[]}, {@code int[]} or {@code long[]} arrays
     * and is ignored for all other kind of arrays.
     *
     * @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.
     * @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, final boolean isUnsigned) throws IllegalArgumentException {
        if (array == null) {
            return null;
        }
        if (array.getClass().isArray()) {
            return ArrayVector.newInstance(array, isUnsigned);
        }
        if (array instanceof Vector) {
            return (Vector) array;
        }
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentClass_2, "array", array.getClass()));
    }

    /**
     * Wraps the given {@code float[]} array in a vector that preserve the string representations in base 10.
     * For example the 0.1 {@code float} value casted to {@code double} normally produces 0.10000000149011612
     * because of the way IEEE 754 arithmetic represents numbers (in base 2 instead than base 10). But the
     * vector returned by this method will convert the 0.1 {@code float} value into the 0.1 {@code double} value.
     * Note that despite the appearance, this is <strong>not</strong> more accurate than the normal cast,
     * because base 10 is not more privileged in nature than base 2.
     *
     * <div class="section">When to use</div>
     * This method can be used when there is good reasons to think that the {@code float} numbers were parsed
     * from decimal representations, for example an ASCII file. There is usually no reason to use this method
     * if the values are the result of some numerical computations.
     *
     * @param  array  the object to wrap in a vector, or {@code null}.
     * @return the given array wrapped in a vector, or {@code null} if the argument was {@code null}.
     *
     * @see DecimalFunctions#floatToDouble(float)
     */
    public static Vector createForDecimal(final float[] array) {
        return (array != null) ? new ArrayVector.Decimal(array) : null;
    }

    /**
     * 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 inferred from the type of the given
     * {@code Number} instances. If will typically be {@code Integer.class} for the [100:1:120] range
     * and {@code Double.class} for the [0:0.1:1] range.</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 Number first, final Number increment, final int length) {
        Class<? extends Number> type;
        type = Numbers.widestClass(first, increment);
        type = Numbers.widestClass(type,
               Numbers.narrowestClass(first.doubleValue() + increment.doubleValue() * (length-1)));
        return createSequence(type, first, increment, length);
    }

    /**
     * Creates a sequence of the given type.
     */
    static Vector createSequence(final Class<? extends Number> type, final Number first, final Number increment, final int length) {
        final int t = Numbers.getEnumConstant(type);
        if (t >= Numbers.BYTE && t <= Numbers.LONG) {
            // Use the long type if possible because not all long values can be represented as double.
            return new SequenceVector.Longs(type, first, increment, length);
        } else {
            return new SequenceVector.Doubles(type, first, increment, length);
        }
    }

    /**
     * For subclasses constructor.
     */
    protected Vector() {
    }

    /**
     * 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}.
     *
     * <p>The information returned by this method is only indicative; it is not guaranteed to specify accurately
     * this kind of objects returned by the {@link #get(int)} method. There is various situation where the types
     * may not match:</p>
     *
     * <ul>
     *   <li>If this vector {@linkplain #isUnsigned() is unsigned}, then the values returned by {@code get(int)}
{'fraction_non_alphanumeric': 0.09923461487413175, 'fraction_numerical': 0.006016900411449808, 'mean_word_length': 3.3236419280795717, 'pattern_counts': {'":': 0, '<': 145, '<?xml version=': 0, '>': 145, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7588706', 'n_tokens_mistral': 6109, 'n_tokens_neox': 5940, 'n_words': 2825}