public double GetQuantile()
        {
            if (totalElementCount == 0)
            {
                throw new EmptySequenceException();
            }
            if (HyndmanFanType != null && !double.IsNaN(probability))
            {
                if (totalElementCount < windowSize)
                {
                    throw new InvalidOperationException($"Sequence should contain at least {windowSize} elements");
                }

                double GetValue(int index)
                {
                    index = (index - 1).Clamp(0, windowSize - 1); // Adapt one-based formula to the zero-based list
                    if (k - 1 <= index && index <= k + 1)
                    {
                        return(h[rootHeapIndex + index - k]);
                    }
                    throw new InvalidOperationException();
                }

                return(HyndmanFanEquations.Evaluate(HyndmanFanType.Value, windowSize, probability, GetValue));
            }

            if (initStrategy == MovingQuantileEstimatorInitStrategy.OrderStatistics && k >= totalElementCount)
            {
                throw new IndexOutOfRangeException($"Not enough values (n = {totalElementCount}, k = {k})");
            }
            return(h[rootHeapIndex]);
        }
 public PartitioningHeapsMovingQuantileEstimator(int windowSize, Probability p, HyndmanFanType HyndmanFanType)
     : this(windowSize, ((int)HyndmanFanEquations.GetH(HyndmanFanType, windowSize, p) - 1).Clamp(0, windowSize - 1))
 {
     this.HyndmanFanType = HyndmanFanType;
     probability         = p;
 }