There are several commonly used methods for estimating percentiles (a.k.a.
quantiles) based on sample data. For large samples, the different methods
agree closely, but when sample sizes are small, different methods will give
significantly different results. The algorithm implemented here works as follows:

Let n be the length of the (sorted) array and
0 < p <= 100 be the desired percentile.

If n = 1 return the unique array element (regardless of
the value of p); otherwise

Compute the estimated percentile position
pos = p * (n + 1) / 100 and the difference, d
between pos and floor(pos) (i.e. the fractional
part of pos).

If pos < 1 return the smallest element in the array.

Else if pos >= n return the largest element in the array.

Else let lower be the element in position
floor(pos) in the array and let upper be the
next element in the array. Return lower + d * (upper - lower)

To compute percentiles, the data must be at least partially ordered. Input
arrays are copied and recursively partitioned using an ordering definition.
The ordering used by Arrays.sort(double[]) is the one determined
by Double.compareTo(Double). This ordering makes
Double.NaN larger than any other value (including
Double.POSITIVE_INFINITY). Therefore, for example, the median
(50th percentile) of
{0, 1, 2, 3, 4, Double.NaN} evaluates to 2.5.

Since percentile estimation usually involves interpolation between array
elements, arrays containing NaN or infinite values will often
result in NaN or infinite values returned.

Further, to include different estimation types such as R1, R2 as mentioned in
Quantile page(wikipedia),
a type specific NaN handling strategy is used to closely match with the
typically observed results from popular tools like R(R1-R9), Excel(R7).

Since 2.2, Percentile uses only selection instead of complete sorting
and caches selection algorithm state between calls to the various
evaluate methods. This greatly improves efficiency, both for a single
percentile and multiple percentile computations. To maximize performance when
multiple percentiles are computed based on the same data, users should set the
data array once using either one of the evaluate(double[], double) or
setData(double[]) methods and thereafter evaluate(double)
with just the percentile provided.

Note that this implementation is not synchronized. If
multiple threads access an instance of this class concurrently, and at least
one of the threads invokes the increment() or
clear() method, it must be synchronized externally.

getWorkArray

Get the work array to operate. Makes use of prior storedData if
it exists or else do a check on NaNs and copy a subset of the array
defined by begin and length parameters. The set nanStrategy will
be used to either retain/remove/replace any NaNs present before returning
the resultant array.