1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/*
2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more
3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements.  See the NOTICE file distributed with
4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership.
5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0
6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with
7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License.  You may obtain a copy of the License at
8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *      http://www.apache.org/licenses/LICENSE-2.0
10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software
12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS,
13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and
15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License.
16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.util;
18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.Serializable;
20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.util.Arrays;
21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException;
23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats;
24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/**
26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>
27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * A variable length {@link DoubleArray} implementation that automatically
28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * handles expanding and contracting its internal storage array as elements
29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * are added and removed.
30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p>
31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>
32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *  The internal storage array starts with capacity determined by the
33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>initialCapacity</code> property, which can be set by the constructor.
34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The default initial capacity is 16.  Adding elements using
35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * {@link #addElement(double)} appends elements to the end of the array.  When
36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * there are no open entries at the end of the internal storage array, the
37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * array is expanded.  The size of the expanded array depends on the
38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>expansionMode</code> and <code>expansionFactor</code> properties.
39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The <code>expansionMode</code> determines whether the size of the array is
40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * multiplied by the <code>expansionFactor</code> (MULTIPLICATIVE_MODE) or if
41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the expansion is additive (ADDITIVE_MODE -- <code>expansionFactor</code>
42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * storage locations added).  The default <code>expansionMode</code> is
43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * MULTIPLICATIVE_MODE and the default <code>expansionFactor</code>
44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is 2.0.
45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p>
46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>
47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The {@link #addElementRolling(double)} method adds a new element to the end
48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * of the internal storage array and adjusts the "usable window" of the
49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * internal array forward by one position (effectively making what was the
50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * second element the first, and so on).  Repeated activations of this method
51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (or activation of {@link #discardFrontElements(int)}) will effectively orphan
52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the storage locations at the beginning of the internal storage array.  To
53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * reclaim this storage, each time one of these methods is activated, the size
54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * of the internal storage array is compared to the number of addressable
55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * elements (the <code>numElements</code> property) and if the difference
56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is too large, the internal array is contracted to size
57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>numElements + 1.</code>  The determination of when the internal
58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * storage array is "too large" depends on the <code>expansionMode</code> and
59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>contractionFactor</code> properties.  If  the <code>expansionMode</code>
60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is <code>MULTIPLICATIVE_MODE</code>, contraction is triggered when the
61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ratio between storage array length and <code>numElements</code> exceeds
62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>contractionFactor.</code>  If the <code>expansionMode</code>
63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is <code>ADDITIVE_MODE,</code> the number of excess storage locations
64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is compared to <code>contractionFactor.</code>
65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p>
66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>
67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * To avoid cycles of expansions and contractions, the
68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>expansionFactor</code> must not exceed the
69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>contractionFactor.</code> Constructors and mutators for both of these
70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * properties enforce this requirement, throwing IllegalArgumentException if it
71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is violated.
72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p>
73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1073474 $ $Date: 2011-02-22 20:52:17 +0100 (mar. 22 févr. 2011) $
74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class ResizableDoubleArray implements DoubleArray, Serializable {
76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** additive expansion mode */
78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static final int ADDITIVE_MODE = 1;
79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** multiplicative expansion mode */
81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static final int MULTIPLICATIVE_MODE = 0;
82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Serializable version identifier */
84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long serialVersionUID = -3485529955529426875L;
85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The contraction criteria determines when the internal array will be
88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * contracted to fit the number of elements contained in the element
89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  array + 1.
90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected float contractionCriteria = 2.5f;
92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The expansion factor of the array.  When the array needs to be expanded,
95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the new array size will be
96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>internalArray.length * expansionFactor</code>
97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if <code>expansionMode</code> is set to MULTIPLICATIVE_MODE, or
98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>internalArray.length + expansionFactor</code> if
99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>expansionMode</code> is set to ADDITIVE_MODE.
100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected float expansionFactor = 2.0f;
102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Determines whether array expansion by <code>expansionFactor</code>
105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * is additive or multiplicative.
106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected int expansionMode = MULTIPLICATIVE_MODE;
108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The initial capacity of the array.  Initial capacity is not exposed as a
111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * property as it is only meaningful when passed to a constructor.
112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected int initialCapacity = 16;
114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The internal storage array.
117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected double[] internalArray;
119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The number of addressable elements in the array.  Note that this
122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * has nothing to do with the length of the internal storage array.
123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected int numElements = 0;
125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The position of the first addressable element in the internal storage
128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * array.  The addressable elements in the array are <code>
129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * internalArray[startIndex],...,internalArray[startIndex + numElements -1]
130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </code>
131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected int startIndex = 0;
133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create a ResizableArray with default properties.
136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>initialCapacity = 16</code></li>
138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionMode = MULTIPLICATIVE_MODE</code></li>
139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionFactor = 2.5</code></li>
140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>contractionFactor = 2.0</code></li>
141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul>
142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public ResizableDoubleArray() {
144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = new double[initialCapacity];
145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create a ResizableArray with the specified initial capacity.  Other
149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * properties take default values:
150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      * <ul>
151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionMode = MULTIPLICATIVE_MODE</code></li>
152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionFactor = 2.5</code></li>
153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>contractionFactor = 2.0</code></li>
154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul>
155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param initialCapacity The initial size of the internal storage array
156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if initialCapacity is not > 0
157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public ResizableDoubleArray(int initialCapacity) {
159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setInitialCapacity(initialCapacity);
160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = new double[this.initialCapacity];
161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create a ResizableArray from an existing double[] with the
165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * initial capacity and numElements corresponding to the size of
166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the supplied double[] array. If the supplied array is null, a
167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * new empty array with the default initial capacity will be created.
168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The input array is copied, not referenced.
169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Other properties take default values:
170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>initialCapacity = 16</code></li>
172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionMode = MULTIPLICATIVE_MODE</code></li>
173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionFactor = 2.5</code></li>
174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>contractionFactor = 2.0</code></li>
175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul>
176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param initialArray initial array
178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public ResizableDoubleArray(double[] initialArray) {
181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (initialArray == null) {
182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            this.internalArray = new double[initialCapacity];
183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            this.internalArray = new double[initialArray.length];
185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            System.arraycopy(initialArray, 0, this.internalArray, 0, initialArray.length);
186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            initialCapacity = initialArray.length;
187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            numElements = initialArray.length;
188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create a ResizableArray with the specified initial capacity
194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * and expansion factor.  The remaining properties take default
195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * values:
196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionMode = MULTIPLICATIVE_MODE</code></li>
198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>contractionFactor = 0.5 + expansionFactor</code></li>
199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul></p>
200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Throws IllegalArgumentException if the following conditions are
202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * not met:
203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>initialCapacity > 0</code></li>
205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionFactor > 1</code></li>
206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul></p>
207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param initialCapacity The initial size of the internal storage array
209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expansionFactor the array will be expanded based on this
210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *                        parameter
211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if parameters are not valid
212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public ResizableDoubleArray(int initialCapacity, float expansionFactor) {
214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.expansionFactor = expansionFactor;
215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setInitialCapacity(initialCapacity);
216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = new double[initialCapacity];
217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setContractionCriteria(expansionFactor +0.5f);
218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create a ResizableArray with the specified initialCapacity,
223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * expansionFactor, and contractionCriteria. The <code>expansionMode</code>
224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * will default to <code>MULTIPLICATIVE_MODE.</code></p>
225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Throws IllegalArgumentException if the following conditions are
227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * not met:
228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>initialCapacity > 0</code></li>
230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionFactor > 1</code></li>
231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>contractionFactor >= expansionFactor</code></li>
232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul></p>
233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param initialCapacity The initial size of the internal storage array
234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expansionFactor the array will be expanded based on this
235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *                        parameter
236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param contractionCriteria The contraction Criteria.
237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if parameters are not valid
238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public ResizableDoubleArray(int initialCapacity, float expansionFactor,
240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        float contractionCriteria) {
241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.expansionFactor = expansionFactor;
242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setContractionCriteria(contractionCriteria);
243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setInitialCapacity(initialCapacity);
244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = new double[initialCapacity];
245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create a ResizableArray with the specified properties.</p>
250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    * <p>
251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Throws IllegalArgumentException if the following conditions are
252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * not met:
253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>initialCapacity > 0</code></li>
255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionFactor > 1</code></li>
256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>contractionFactor >= expansionFactor</code></li>
257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionMode in {MULTIPLICATIVE_MODE, ADDITIVE_MODE}</code>
258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </li>
259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul></p>
260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param initialCapacity the initial size of the internal storage array
262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expansionFactor the array will be expanded based on this
263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *                        parameter
264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param contractionCriteria the contraction Criteria
265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expansionMode  the expansion mode
266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if parameters are not valid
267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public ResizableDoubleArray(int initialCapacity, float expansionFactor,
269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            float contractionCriteria, int expansionMode) {
270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.expansionFactor = expansionFactor;
271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setContractionCriteria(contractionCriteria);
272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setInitialCapacity(initialCapacity);
273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setExpansionMode(expansionMode);
274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = new double[initialCapacity];
275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Copy constructor.  Creates a new ResizableDoubleArray that is a deep,
279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * fresh copy of the original. Needs to acquire synchronization lock
280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * on original.  Original may not be null; otherwise a NullPointerException
281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * is thrown.
282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param original array to copy
284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public ResizableDoubleArray(ResizableDoubleArray original) {
287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        copy(original, this);
288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Adds an element to the end of this expandable array.
292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param value to be added to end of array
294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void addElement(double value) {
296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        numElements++;
297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((startIndex + numElements) > internalArray.length) {
298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            expand();
299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray[startIndex + (numElements - 1)] = value;
301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (shouldContract()) {
302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            contract();
303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Adds several element to the end of this expandable array.
308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param values to be added to end of array
310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void addElements(double[] values) {
313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double[] tempArray = new double[numElements + values.length + 1];
314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        System.arraycopy(internalArray, startIndex, tempArray, 0, numElements);
315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        System.arraycopy(values, 0, tempArray, numElements, values.length);
316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = tempArray;
317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        startIndex = 0;
318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        numElements += values.length;
319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Adds an element to the end of the array and removes the first
324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * element in the array.  Returns the discarded first element.
325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The effect is similar to a push operation in a FIFO queue.
326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </p>
327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Example: If the array contains the elements 1, 2, 3, 4 (in that order)
329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * and addElementRolling(5) is invoked, the result is an array containing
330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the entries 2, 3, 4, 5 and the value returned is 1.
331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </p>
332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param value the value to be added to the array
334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the value which has been discarded or "pushed" out of the array
335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         by this rolling insert
336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized double addElementRolling(double value) {
338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double discarded = internalArray[startIndex];
339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((startIndex + (numElements + 1)) > internalArray.length) {
341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            expand();
342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Increment the start index
344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        startIndex += 1;
345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Add the new value
347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray[startIndex + (numElements - 1)] = value;
348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Check the contraction criteria
350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (shouldContract()) {
351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            contract();
352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return discarded;
354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Substitutes <code>value</code> for the most recently added value.
358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the value that has been replaced. If the array is empty (i.e.
359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if {@link #numElements} is zero), a MathRuntimeException is thrown.
360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param value new value to substitute for the most recently added value
362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return value that has been replaced in the array
363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized double substituteMostRecentElement(double value) {
366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (numElements < 1) {
367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createArrayIndexOutOfBoundsException(
368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.CANNOT_SUBSTITUTE_ELEMENT_FROM_EMPTY_ARRAY);
369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double discarded = internalArray[startIndex + (numElements - 1)];
372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray[startIndex + (numElements - 1)] = value;
374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return discarded;
376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Checks the expansion factor and the contraction criteria and throws an
381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * IllegalArgumentException if the contractionCriteria is less than the
382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * expansionCriteria
383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expansion factor to be checked
385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param contraction criteria to be checked
386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if the contractionCriteria is less than
387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         the expansionCriteria.
388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected void checkContractExpand(float contraction, float expansion) {
390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (contraction < expansion) {
392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.CONTRACTION_CRITERIA_SMALLER_THAN_EXPANSION_FACTOR,
394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    contraction, expansion);
395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (contraction <= 1.0) {
398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.CONTRACTION_CRITERIA_SMALLER_THAN_ONE,
400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    contraction);
401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (expansion <= 1.0) {
404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.EXPANSION_FACTOR_SMALLER_THAN_ONE,
406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    expansion);
407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Clear the array, reset the size to the initialCapacity and the number
412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * of elements to zero.
413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void clear() {
415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        numElements = 0;
416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        startIndex = 0;
417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = new double[initialCapacity];
418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Contracts the storage array to the (size of the element set) + 1 - to
422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * avoid a zero length array. This function also resets the startIndex to
423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * zero.
424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void contract() {
426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double[] tempArray = new double[numElements + 1];
427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Copy and swap - copy only the element array from the src array.
429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        System.arraycopy(internalArray, startIndex, tempArray, 0, numElements);
430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = tempArray;
431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Reset the start index to zero
433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        startIndex = 0;
434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Discards the <code>i<code> initial elements of the array.  For example,
438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if the array contains the elements 1,2,3,4, invoking
439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>discardFrontElements(2)</code> will cause the first two elements
440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to be discarded, leaving 3,4 in the array.  Throws illegalArgumentException
441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if i exceeds numElements.
442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param i  the number of elements to discard from the front of the array
444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if i is greater than numElements.
445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void discardFrontElements(int i) {
448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        discardExtremeElements(i,true);
450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Discards the <code>i<code> last elements of the array.  For example,
455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if the array contains the elements 1,2,3,4, invoking
456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>discardMostRecentElements(2)</code> will cause the last two elements
457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to be discarded, leaving 1,2 in the array.  Throws illegalArgumentException
458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if i exceeds numElements.
459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param i  the number of elements to discard from the end of the array
461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if i is greater than numElements.
462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void discardMostRecentElements(int i) {
465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        discardExtremeElements(i,false);
467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Discards the <code>i<code> first or last elements of the array,
472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * depending on the value of <code>front</code>.
473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For example, if the array contains the elements 1,2,3,4, invoking
474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>discardExtremeElements(2,false)</code> will cause the last two elements
475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to be discarded, leaving 1,2 in the array.
476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For example, if the array contains the elements 1,2,3,4, invoking
477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>discardExtremeElements(2,true)</code> will cause the first two elements
478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to be discarded, leaving 3,4 in the array.
479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Throws illegalArgumentException
480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if i exceeds numElements.
481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param i  the number of elements to discard from the front/end of the array
483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param front true if elements are to be discarded from the front
484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * of the array, false if elements are to be discarded from the end
485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * of the array
486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if i is greater than numElements.
487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private synchronized void discardExtremeElements(int i,boolean front) {
490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (i > numElements) {
491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.TOO_MANY_ELEMENTS_TO_DISCARD_FROM_ARRAY,
493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    i, numElements);
494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       } else if (i < 0) {
495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond           throw MathRuntimeException.createIllegalArgumentException(
496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                   LocalizedFormats.CANNOT_DISCARD_NEGATIVE_NUMBER_OF_ELEMENTS,
497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                   i);
498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // "Subtract" this number of discarded from numElements
500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            numElements -= i;
501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (front) startIndex += i;
502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (shouldContract()) {
504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            contract();
505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Expands the internal storage array using the expansion factor.
510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * if <code>expansionMode</code> is set to MULTIPLICATIVE_MODE,
512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the new array size will be <code>internalArray.length * expansionFactor.</code>
513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If <code>expansionMode</code> is set to ADDITIVE_MODE,  the length
514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * after expansion will be <code>internalArray.length + expansionFactor</code>
515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </p>
516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected synchronized void expand() {
518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // notice the use of FastMath.ceil(), this guarantees that we will always
520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // have an array of at least currentSize + 1.   Assume that the
521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // current initial capacity is 1 and the expansion factor
522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // is 1.000000000000000001.  The newly calculated size will be
523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // rounded up to 2 after the multiplication is performed.
524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int newSize = 0;
525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (expansionMode == MULTIPLICATIVE_MODE) {
526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            newSize = (int) FastMath.ceil(internalArray.length * expansionFactor);
527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            newSize = internalArray.length + FastMath.round(expansionFactor);
529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double[] tempArray = new double[newSize];
531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Copy and swap
533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length);
534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = tempArray;
535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Expands the internal storage array to the specified size.
539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param size Size of the new internal storage array
541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private synchronized void expandTo(int size) {
543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double[] tempArray = new double[size];
544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Copy and swap
545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length);
546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray = tempArray;
547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The contraction criteria defines when the internal array will contract
551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to store only the number of elements in the element array.
552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If  the <code>expansionMode</code> is <code>MULTIPLICATIVE_MODE</code>,
553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * contraction is triggered when the ratio between storage array length
554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * and <code>numElements</code> exceeds <code>contractionFactor</code>.
555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If the <code>expansionMode</code> is <code>ADDITIVE_MODE</code>, the
556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * number of excess storage locations is compared to
557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>contractionFactor.</code>
558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the contraction criteria used to reclaim memory.
560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public float getContractionCriteria() {
562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return contractionCriteria;
563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the element at the specified index
567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param index index to fetch a value from
569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return value stored at the specified index
570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws ArrayIndexOutOfBoundsException if <code>index</code> is less than
571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         zero or is greater than <code>getNumElements() - 1</code>.
572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized double getElement(int index) {
574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (index >= numElements) {
575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createArrayIndexOutOfBoundsException(
576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.INDEX_LARGER_THAN_MAX,
577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    index, numElements - 1);
578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (index >= 0) {
579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return internalArray[startIndex + index];
580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createArrayIndexOutOfBoundsException(
582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.CANNOT_RETRIEVE_AT_NEGATIVE_INDEX,
583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    index);
584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /**
588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns a double array containing the elements of this
589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>ResizableArray</code>.  This method returns a copy, not a
590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * reference to the underlying array, so that changes made to the returned
591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  array have no effect on this <code>ResizableArray.</code>
592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the double array.
593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized double[] getElements() {
595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double[] elementArray = new double[numElements];
596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        System.arraycopy( internalArray, startIndex, elementArray, 0,
597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                numElements);
598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return elementArray;
599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The expansion factor controls the size of a new array when an array
603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * needs to be expanded.  The <code>expansionMode</code>
604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * determines whether the size of the array is multiplied by the
605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>expansionFactor</code> (MULTIPLICATIVE_MODE) or if
606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the expansion is additive (ADDITIVE_MODE -- <code>expansionFactor</code>
607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * storage locations added).  The default <code>expansionMode</code> is
608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * MULTIPLICATIVE_MODE and the default <code>expansionFactor</code>
609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * is 2.0.
610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the expansion factor of this expandable double array
612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public float getExpansionFactor() {
614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return expansionFactor;
615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The <code>expansionMode</code> determines whether the internal storage
619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * array grows additively (ADDITIVE_MODE) or multiplicatively
620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * (MULTIPLICATIVE_MODE) when it is expanded.
621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return Returns the expansionMode.
623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int getExpansionMode() {
625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return expansionMode;
626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Notice the package scope on this method.   This method is simply here
630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * for the JUnit test, it allows us check if the expansion is working
631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * properly after a number of expansions.  This is not meant to be a part
632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * of the public interface of this class.
633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the length of the internal storage array.
635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    synchronized int getInternalLength() {
637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return internalArray.length;
638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the number of elements currently in the array.  Please note
642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * that this is different from the length of the internal storage array.
643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return number of elements
645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized int getNumElements() {
647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return numElements;
648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the internal storage array.  Note that this method returns
652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * a reference to the internal storage array, not a copy, and to correctly
653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * address elements of the array, the <code>startIndex</code> is
654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * required (available via the {@link #start} method).  This method should
655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * only be used in cases where copying the internal array is not practical.
656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The {@link #getElements} method should be used in all other cases.
657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
658dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
659dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the internal storage array used by this object
660dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @deprecated replaced by {@link #getInternalValues()} as of 2.0
661dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
662dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Deprecated
663dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized double[] getValues() {
664dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return internalArray;
665dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
666dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
667dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
668dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the internal storage array.  Note that this method returns
669dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * a reference to the internal storage array, not a copy, and to correctly
670dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * address elements of the array, the <code>startIndex</code> is
671dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * required (available via the {@link #start} method).  This method should
672dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * only be used in cases where copying the internal array is not practical.
673dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The {@link #getElements} method should be used in all other cases.
674dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
675dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
676dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the internal storage array used by this object
677dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
678dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
679dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized double[] getInternalValues() {
680dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return internalArray;
681dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
682dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
683dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
684dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Sets the contraction criteria for this ExpandContractDoubleArray.
685dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
686dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param contractionCriteria contraction criteria
687dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
688dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setContractionCriteria(float contractionCriteria) {
689dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkContractExpand(contractionCriteria, getExpansionFactor());
690dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        synchronized(this) {
691dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            this.contractionCriteria = contractionCriteria;
692dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
693dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
694dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
695dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
696dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
697dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Sets the element at the specified index.  If the specified index is greater than
698dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>getNumElements() - 1</code>, the <code>numElements</code> property
699dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * is increased to <code>index +1</code> and additional storage is allocated
700dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * (if necessary) for the new element and all  (uninitialized) elements
701dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * between the new element and the previous end of the array).
702dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
703dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param index index to store a value in
704dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param value value to store at the specified index
705dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws ArrayIndexOutOfBoundsException if <code>index</code> is less than
706dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         zero.
707dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
708dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void setElement(int index, double value) {
709dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (index < 0) {
710dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createArrayIndexOutOfBoundsException(
711dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.CANNOT_SET_AT_NEGATIVE_INDEX,
712dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    index);
713dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
714dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (index + 1 > numElements) {
715dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            numElements = index + 1;
716dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
717dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((startIndex + index) >= internalArray.length) {
718dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            expandTo(startIndex + (index + 1));
719dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
720dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        internalArray[startIndex + index] = value;
721dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
722dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
723dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
724dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Sets the expansionFactor.  Throws IllegalArgumentException if the
725dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the following conditions are not met:
726dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
727dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>expansionFactor > 1</code></li>
728dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li><code>contractionFactor >= expansionFactor</code></li>
729dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul>
730dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expansionFactor the new expansion factor value.
731dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if expansionFactor is <= 1 or greater
732dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * than contractionFactor
733dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
734dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setExpansionFactor(float expansionFactor) {
735dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkContractExpand(getContractionCriteria(), expansionFactor);
736dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // The check above verifies that the expansion factor is > 1.0;
737dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        synchronized(this) {
738dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            this.expansionFactor = expansionFactor;
739dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
740dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
741dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
742dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
743dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Sets the <code>expansionMode</code>. The specified value must be one of
744dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * ADDITIVE_MODE, MULTIPLICATIVE_MODE.
745dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
746dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expansionMode The expansionMode to set.
747dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if the specified mode value is not valid
748dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
749dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setExpansionMode(int expansionMode) {
750dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (expansionMode != MULTIPLICATIVE_MODE &&
751dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                expansionMode != ADDITIVE_MODE) {
752dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
753dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.UNSUPPORTED_EXPANSION_MODE,
754dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    expansionMode, MULTIPLICATIVE_MODE, "MULTIPLICATIVE_MODE",
755dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    ADDITIVE_MODE, "ADDITIVE_MODE");
756dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
757dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        synchronized(this) {
758dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            this.expansionMode = expansionMode;
759dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
760dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
761dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
762dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
763dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Sets the initial capacity.  Should only be invoked by constructors.
764dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
765dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param initialCapacity of the array
766dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>initialCapacity</code> is not
767dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         positive.
768dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
769dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected void setInitialCapacity(int initialCapacity) {
770dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (initialCapacity > 0) {
771dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            synchronized(this) {
772dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                this.initialCapacity = initialCapacity;
773dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
774dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
775dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
776dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.INITIAL_CAPACITY_NOT_POSITIVE,
777dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    initialCapacity);
778dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
779dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
780dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
781dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
782dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * This function allows you to control the number of elements contained
783dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * in this array, and can be used to "throw out" the last n values in an
784dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * array. This function will also expand the internal array as needed.
785dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
786dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param i a new number of elements
787dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>i</code> is negative.
788dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
789dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized void setNumElements(int i) {
790dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
791dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // If index is negative thrown an error
792dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (i < 0) {
793dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
794dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.INDEX_NOT_POSITIVE,
795dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    i);
796dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
797dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
798dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Test the new num elements, check to see if the array needs to be
799dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // expanded to accommodate this new number of elements
800dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((startIndex + i) > internalArray.length) {
801dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            expandTo(startIndex + i);
802dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
803dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
804dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Set the new number of elements to new value
805dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        numElements = i;
806dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
807dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
808dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
809dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns true if the internal storage array has too many unused
810dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * storage positions.
811dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
812dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return true if array satisfies the contraction criteria
813dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
814dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private synchronized boolean shouldContract() {
815dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (expansionMode == MULTIPLICATIVE_MODE) {
816dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (internalArray.length / ((float) numElements)) > contractionCriteria;
817dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
818dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (internalArray.length - numElements) > contractionCriteria;
819dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
820dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
821dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
822dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
823dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the starting index of the internal array.  The starting index is
824dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the position of the first addressable element in the internal storage
825dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * array.  The addressable elements in the array are <code>
826dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * internalArray[startIndex],...,internalArray[startIndex + numElements -1]
827dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </code>
828dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
829dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return starting index
830dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
831dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized int start() {
832dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return startIndex;
833dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
834dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
835dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
836dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>Copies source to dest, copying the underlying data, so dest is
837dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * a new, independent copy of source.  Does not contract before
838dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the copy.</p>
839dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
840dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>Obtains synchronization locks on both source and dest
841dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * (in that order) before performing the copy.</p>
842dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
843dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>Neither source nor dest may be null; otherwise a NullPointerException
844dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * is thrown</p>
845dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
846dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param source ResizableDoubleArray to copy
847dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param dest ResizableArray to replace with a copy of the source array
848dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
849dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
850dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
851dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static void copy(ResizableDoubleArray source, ResizableDoubleArray dest) {
852dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       synchronized(source) {
853dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond           synchronized(dest) {
854dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               dest.initialCapacity = source.initialCapacity;
855dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               dest.contractionCriteria = source.contractionCriteria;
856dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               dest.expansionFactor = source.expansionFactor;
857dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               dest.expansionMode = source.expansionMode;
858dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               dest.internalArray = new double[source.internalArray.length];
859dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               System.arraycopy(source.internalArray, 0, dest.internalArray,
860dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                       0, dest.internalArray.length);
861dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               dest.numElements = source.numElements;
862dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               dest.startIndex = source.startIndex;
863dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond           }
864dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       }
865dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
866dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
867dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
868dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns a copy of the ResizableDoubleArray.  Does not contract before
869dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the copy, so the returned object is an exact copy of this.
870dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
871dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a new ResizableDoubleArray with the same data and configuration
872dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * properties as this
873dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
874dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
875dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized ResizableDoubleArray copy() {
876dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ResizableDoubleArray result = new ResizableDoubleArray();
877dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        copy(this, result);
878dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
879dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
880dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
881dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
882dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns true iff object is a ResizableDoubleArray with the same properties
883dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * as this and an identical internal storage array.
884dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
885dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param object object to be compared for equality with this
886dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return true iff object is a ResizableDoubleArray with the same data and
887dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * properties as this
888dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
889dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
890dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
891dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public boolean equals(Object object) {
892dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (object == this ) {
893dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return true;
894dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
895dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       if (object instanceof ResizableDoubleArray == false) {
896dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return false;
897dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
898dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       synchronized(this) {
899dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond           synchronized(object) {
900dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               boolean result = true;
901dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               ResizableDoubleArray other = (ResizableDoubleArray) object;
902dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               result = result && (other.initialCapacity == initialCapacity);
903dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               result = result && (other.contractionCriteria == contractionCriteria);
904dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               result = result && (other.expansionFactor == expansionFactor);
905dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               result = result && (other.expansionMode == expansionMode);
906dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               result = result && (other.numElements == numElements);
907dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               result = result && (other.startIndex == startIndex);
908dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               if (!result) {
909dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                   return false;
910dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               } else {
911dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                   return Arrays.equals(internalArray, other.internalArray);
912dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               }
913dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond           }
914dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       }
915dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
916dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
917dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
918dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns a hash code consistent with equals.
919dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
920dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return hash code representing this ResizableDoubleArray
921dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.0
922dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
923dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
924dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public synchronized int hashCode() {
925dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int[] hashData = new int[7];
926dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        hashData[0] = new Float(expansionFactor).hashCode();
927dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        hashData[1] = new Float(contractionCriteria).hashCode();
928dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        hashData[2] = expansionMode;
929dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hashData[3] = Arrays.hashCode(internalArray);
930dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hashData[4] = initialCapacity;
931dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hashData[5] = numElements;
932dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hashData[6] = startIndex;
933dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return Arrays.hashCode(hashData);
934dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
935dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
936dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond}
937