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.stat.descriptive.rank; 18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.Serializable; 20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.util.Arrays; 21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException; 23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats; 24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.stat.descriptive.AbstractUnivariateStatistic; 25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.FastMath; 26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/** 28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Provides percentile computation. 29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * There are several commonly used methods for estimating percentiles (a.k.a. 31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * quantiles) based on sample data. For large samples, the different methods 32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * agree closely, but when sample sizes are small, different methods will give 33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * significantly different results. The algorithm implemented here works as follows: 34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ol> 35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Let <code>n</code> be the length of the (sorted) array and 36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>0 < p <= 100</code> be the desired percentile.</li> 37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>If <code> n = 1 </code> return the unique array element (regardless of 38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the value of <code>p</code>); otherwise </li> 39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Compute the estimated percentile position 40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code> pos = p * (n + 1) / 100</code> and the difference, <code>d</code> 41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * between <code>pos</code> and <code>floor(pos)</code> (i.e. the fractional 42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * part of <code>pos</code>). If <code>pos >= n</code> return the largest 43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * element in the array; otherwise</li> 44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Let <code>lower</code> be the element in position 45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>floor(pos)</code> in the array and let <code>upper</code> be the 46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * next element in the array. Return <code>lower + d * (upper - lower)</code> 47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </li> 48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ol></p> 49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * To compute percentiles, the data must be at least partially ordered. Input 51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * arrays are copied and recursively partitioned using an ordering definition. 52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ordering used by <code>Arrays.sort(double[])</code> is the one determined 53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * by {@link java.lang.Double#compareTo(Double)}. This ordering makes 54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>Double.NaN</code> larger than any other value (including 55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>Double.POSITIVE_INFINITY</code>). Therefore, for example, the median 56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (50th percentile) of 57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>{0, 1, 2, 3, 4, Double.NaN}</code> evaluates to <code>2.5.</code></p> 58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Since percentile estimation usually involves interpolation between array 60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * elements, arrays containing <code>NaN</code> or infinite values will often 61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * result in <code>NaN<code> or infinite values returned.</p> 62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Since 2.2, Percentile implementation uses only selection instead of complete 64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * sorting and caches selection algorithm state between calls to the various 65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * {@code evaluate} methods when several percentiles are to be computed on the same data. 66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * This greatly improves efficiency, both for single percentile and multiple 67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * percentiles computations. However, it also induces a need to be sure the data 68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * at one call to {@code evaluate} is the same as the data with the cached algorithm 69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * state from the previous calls. Percentile does this by checking the array reference 70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * itself and a checksum of its content by default. If the user already knows he calls 71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * {@code evaluate} on an immutable array, he can save the checking time by calling the 72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * {@code evaluate} methods that do <em>not</em> 73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p> 74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <strong>Note that this implementation is not synchronized.</strong> If 76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * multiple threads access an instance of this class concurrently, and at least 77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * one of the threads invokes the <code>increment()</code> or 78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>clear()</code> method, it must be synchronized externally.</p> 79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1006299 $ $Date: 2010-10-10 16:47:17 +0200 (dim. 10 oct. 2010) $ 81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class Percentile extends AbstractUnivariateStatistic implements Serializable { 83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Serializable version identifier */ 85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final long serialVersionUID = -8091216485095130416L; 86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Minimum size under which we use a simple insertion sort rather than Hoare's select. */ 88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final int MIN_SELECT_SIZE = 15; 89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Maximum number of partitioning pivots cached (each level double the number of pivots). */ 91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final int MAX_CACHED_LEVELS = 10; 92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Determines what percentile is computed when evaluate() is activated 94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * with no quantile argument */ 95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private double quantile = 0.0; 96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Cached pivots. */ 98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int[] cachedPivots; 99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Constructs a Percentile with a default quantile 102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * value of 50.0. 103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public Percentile() { 105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this(50.0); 106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Constructs a Percentile with the specific quantile value. 110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param p the quantile 111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if p is not greater than 0 and less 112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * than or equal to 100 113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public Percentile(final double p) { 115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond setQuantile(p); 116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond cachedPivots = null; 117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Copy constructor, creates a new {@code Percentile} identical 121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to the {@code original} 122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param original the {@code Percentile} instance to copy 124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public Percentile(Percentile original) { 126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond copy(original, this); 127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setData(final double[] values) { 132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (values == null) { 133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond cachedPivots = null; 134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond cachedPivots = new int[(0x1 << MAX_CACHED_LEVELS) - 1]; 136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Arrays.fill(cachedPivots, -1); 137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond super.setData(values); 139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setData(final double[] values, final int begin, final int length) { 144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (values == null) { 145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond cachedPivots = null; 146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond cachedPivots = new int[(0x1 << MAX_CACHED_LEVELS) - 1]; 148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Arrays.fill(cachedPivots, -1); 149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond super.setData(values, begin, length); 151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the result of evaluating the statistic over the stored data. 155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The stored array is the one which was set by previous calls to 157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p> 158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param p the percentile value to compute 159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the value of the statistic applied to the stored data 160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double evaluate(final double p) { 162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return evaluate(getDataRef(), p); 163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns an estimate of the <code>p</code>th percentile of the values 167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * in the <code>values</code> array. 168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Calls to this method do not modify the internal <code>quantile</code> 170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * state of this statistic.</p> 171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul> 173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Returns <code>Double.NaN</code> if <code>values</code> has length 174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>0</code></li> 175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Returns (for any value of <code>p</code>) <code>values[0]</code> 176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if <code>values</code> has length <code>1</code></li> 177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Throws <code>IllegalArgumentException</code> if <code>values</code> 178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is null or p is not a valid quantile value (p must be greater than 0 179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * and less than or equal to 100) </li> 180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul></p> 181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See {@link Percentile} for a description of the percentile estimation 183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * algorithm used.</p> 184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param values input array of values 186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param p the percentile value to compute 187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the percentile value or Double.NaN if the array is empty 188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if <code>values</code> is null 189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * or p is invalid 190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double evaluate(final double[] values, final double p) { 192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond test(values, 0, 0); 193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return evaluate(values, 0, values.length, p); 194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns an estimate of the <code>quantile</code>th percentile of the 198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * designated values in the <code>values</code> array. The quantile 199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * estimated is determined by the <code>quantile</code> property. 200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul> 202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Returns <code>Double.NaN</code> if <code>length = 0</code></li> 203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Returns (for any value of <code>quantile</code>) 204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>values[begin]</code> if <code>length = 1 </code></li> 205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Throws <code>IllegalArgumentException</code> if <code>values</code> 206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is null, or <code>start</code> or <code>length</code> 207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is invalid</li> 208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul></p> 209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See {@link Percentile} for a description of the percentile estimation 211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * algorithm used.</p> 212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param values the input array 214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param start index of the first array element to include 215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param length the number of elements to include 216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the percentile value 217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if the parameters are not valid 218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double evaluate( final double[] values, final int start, final int length) { 222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return evaluate(values, start, length, quantile); 223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns an estimate of the <code>p</code>th percentile of the values 227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * in the <code>values</code> array, starting with the element in (0-based) 228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * position <code>begin</code> in the array and including <code>length</code> 229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * values. 230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Calls to this method do not modify the internal <code>quantile</code> 232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * state of this statistic.</p> 233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul> 235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Returns <code>Double.NaN</code> if <code>length = 0</code></li> 236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Returns (for any value of <code>p</code>) <code>values[begin]</code> 237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if <code>length = 1 </code></li> 238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>Throws <code>IllegalArgumentException</code> if <code>values</code> 239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * is null , <code>begin</code> or <code>length</code> is invalid, or 240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <code>p</code> is not a valid quantile value (p must be greater than 0 241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * and less than or equal to 100)</li> 242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul></p> 243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See {@link Percentile} for a description of the percentile estimation 245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * algorithm used.</p> 246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param values array of input values 248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param p the percentile to compute 249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param begin the first (0-based) element to include in the computation 250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param length the number of array elements to include 251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the percentile value 252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if the parameters are not valid or the 253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * input array is null 254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double evaluate(final double[] values, final int begin, 256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int length, final double p) { 257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond test(values, begin, length); 259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if ((p > 100) || (p <= 0)) { 261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.OUT_OF_BOUNDS_QUANTILE_VALUE, p); 263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (length == 0) { 265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return Double.NaN; 266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (length == 1) { 268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return values[begin]; // always return single value for n = 1 269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double n = length; 271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double pos = p * (n + 1) / 100; 272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double fpos = FastMath.floor(pos); 273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int intPos = (int) fpos; 274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double dif = pos - fpos; 275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double[] work; 276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int[] pivotsHeap; 277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (values == getDataRef()) { 278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work = getDataRef(); 279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond pivotsHeap = cachedPivots; 280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work = new double[length]; 282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(values, begin, work, 0, length); 283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond pivotsHeap = new int[(0x1 << MAX_CACHED_LEVELS) - 1]; 284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Arrays.fill(pivotsHeap, -1); 285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (pos < 1) { 288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return select(work, pivotsHeap, 0); 289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (pos >= n) { 291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return select(work, pivotsHeap, length - 1); 292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double lower = select(work, pivotsHeap, intPos - 1); 294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double upper = select(work, pivotsHeap, intPos); 295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return lower + dif * (upper - lower); 296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Select the k<sup>th</sup> smallest element from work array 300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param work work array (will be reorganized during the call) 301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param pivotsHeap set of pivot index corresponding to elements that 302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * are already at their sorted location, stored as an implicit heap 303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (i.e. a sorted binary tree stored in a flat array, where the 304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * children of a node at index n are at indices 2n+1 for the left 305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * child and 2n+2 for the right child, with 0-based indices) 306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param k index of the desired element 307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return k<sup>th</sup> smallest element 308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private double select(final double[] work, final int[] pivotsHeap, final int k) { 310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int begin = 0; 312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int end = work.length; 313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int node = 0; 314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while (end - begin > MIN_SELECT_SIZE) { 316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int pivot; 318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if ((node < pivotsHeap.length) && (pivotsHeap[node] >= 0)) { 319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // the pivot has already been found in a previous call 320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // and the array has already been partitioned around it 321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond pivot = pivotsHeap[node]; 322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // select a pivot and partition work array around it 324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond pivot = partition(work, begin, end, medianOf3(work, begin, end)); 325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (node < pivotsHeap.length) { 326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond pivotsHeap[node] = pivot; 327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (k == pivot) { 331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // the pivot was exactly the element we wanted 332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return work[k]; 333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else if (k < pivot) { 334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // the element is in the left partition 335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond end = pivot; 336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond node = Math.min(2 * node + 1, pivotsHeap.length); // the min is here to avoid integer overflow 337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // the element is in the right partition 339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond begin = pivot + 1; 340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond node = Math.min(2 * node + 2, pivotsHeap.length); // the min is here to avoid integer overflow 341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // the element is somewhere in the small sub-array 346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // sort the sub-array using insertion sort 347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond insertionSort(work, begin, end); 348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return work[k]; 349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Select a pivot index as the median of three 353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param work data array 354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param begin index of the first element of the slice 355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param end index after the last element of the slice 356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return the index of the median element chosen between the 357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * first, the middle and the last element of the array slice 358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int medianOf3(final double[] work, final int begin, final int end) { 360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int inclusiveEnd = end - 1; 362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int middle = begin + (inclusiveEnd - begin) / 2; 363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double wBegin = work[begin]; 364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double wMiddle = work[middle]; 365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double wEnd = work[inclusiveEnd]; 366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (wBegin < wMiddle) { 368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (wMiddle < wEnd) { 369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return middle; 370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return (wBegin < wEnd) ? inclusiveEnd : begin; 372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (wBegin < wEnd) { 375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return begin; 376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return (wMiddle < wEnd) ? inclusiveEnd : middle; 378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Partition an array slice around a pivot 385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Partitioning exchanges array elements such that all elements 387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * smaller than pivot are before it and all elements larger than 388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * pivot are after it 389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p> 390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param work data array 391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param begin index of the first element of the slice 392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param end index after the last element of the slice 393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param pivot initial index of the pivot 394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return index of the pivot after partition 395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int partition(final double[] work, final int begin, final int end, final int pivot) { 397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double value = work[pivot]; 399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work[pivot] = work[begin]; 400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int i = begin + 1; 402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int j = end - 1; 403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while (i < j) { 404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while ((i < j) && (work[j] >= value)) { 405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond --j; 406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while ((i < j) && (work[i] <= value)) { 408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ++i; 409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (i < j) { 412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double tmp = work[i]; 413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work[i++] = work[j]; 414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work[j--] = tmp; 415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if ((i >= end) || (work[i] > value)) { 419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond --i; 420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work[begin] = work[i]; 422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work[i] = value; 423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return i; 424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Sort in place a (small) array slice using insertion sort 429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param work array to sort 430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param begin index of the first element of the slice to sort 431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param end index after the last element of the slice to sort 432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private void insertionSort(final double[] work, final int begin, final int end) { 434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = begin + 1; j < end; j++) { 435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double saved = work[j]; 436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int i = j - 1; 437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while ((i >= begin) && (saved < work[i])) { 438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work[i + 1] = work[i]; 439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond i--; 440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond work[i + 1] = saved; 442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Returns the value of the quantile field (determines what percentile is 447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * computed when evaluate() is called with no quantile argument). 448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return quantile 450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double getQuantile() { 452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return quantile; 453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Sets the value of the quantile field (determines what percentile is 457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * computed when evaluate() is called with no quantile argument). 458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param p a value between 0 < p <= 100 460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws IllegalArgumentException if p is not greater than 0 and less 461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * than or equal to 100 462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setQuantile(final double p) { 464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (p <= 0 || p > 100) { 465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalArgumentException( 466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.OUT_OF_BOUNDS_QUANTILE_VALUE, p); 467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond quantile = p; 469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * {@inheritDoc} 473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond @Override 475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public Percentile copy() { 476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Percentile result = new Percentile(); 477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond copy(this, result); 478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result; 479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Copies source to dest. 483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>Neither source nor dest can be null.</p> 484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param source Percentile to copy 486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param dest Percentile to copy to 487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @throws NullPointerException if either source or dest is null 488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static void copy(Percentile source, Percentile dest) { 490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond dest.setData(source.getDataRef()); 491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (source.cachedPivots != null) { 492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond System.arraycopy(source.cachedPivots, 0, dest.cachedPivots, 0, source.cachedPivots.length); 493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond dest.quantile = source.quantile; 495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond} 498