/// <summary>
        /// Computes the specified quantile elements over the values previously added.
        /// </summary>
        /// <param name="phis">the quantiles for which elements are to be computed. Each phi must be in the interval [0.0,1.0]. <tt>phis</tt> must be sorted ascending.</param>
        /// <returns>the approximate quantile elements.</returns>
        public virtual DoubleArrayList QuantileElements(DoubleArrayList phis)
        {
            /*
             * //check parameter
             */
            List <Double> sortedPhiList = phis.Copy().ToList();

            sortedPhiList.Sort();
            if (!phis.Equals(sortedPhiList))
            {
                throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_PhisMustBeAscending);
            }

            //System.out.println("starting to augment missing values, if necessary...");

            phis = PreProcessPhis(phis);

            long[] triggerPositions = new long[phis.Size];
            long   totalSize        = this.bufferSet.TotalSize;

            for (int i = phis.Size; --i >= 0;)
            {
                triggerPositions[i] = Utils.EpsilonCeiling(phis[i] * totalSize) - 1;
            }

            //System.out.println("triggerPositions="+cern.colt.Arrays.ToString(triggerPositions));
            //System.out.println("starting to determine quantiles...");
            //System.out.println(bufferSet);

            DoubleBuffer[] fullBuffers      = bufferSet.GetFullOrPartialBuffers();
            double[]       quantileElements = new double[phis.Size];

            //do the main work: determine values at given positions in sorted sequence
            return(new DoubleArrayList(bufferSet.GetValuesAtPositions(fullBuffers, triggerPositions)));
        }