@SuppressWarnings("unchecked")
  public SumResult<T> extendedSum(double p) throws SumOutOfRangeException {
    SumResult<T> result;
    
    if (_bins.getBins().isEmpty()) {
      throw new SumOutOfRangeException("Cannot sum with an empty histogram.");
    }

    if (Double.isNaN(p)) {
      throw new SumOutOfRangeException("Cannot compute a histogram sum for NaN");
    }

    double binMax = _bins.last().getMean();

    if (p < _minimum) {
      result = new SumResult<T>(0, (T) _bins.first().getTarget().init());
    } else if (p >= _maximum) {
      result = new SumResult<T>(getTotalCount(), getTotalTargetSum());
    } else if (p == binMax) {
      Bin<T> lastBin = _bins.last();

      double totalCount = this.getTotalCount();
      double count = totalCount - (lastBin.getCount() / 2d);
      T targetSum = (T) getTotalTargetSum().sum(lastBin.getTarget().clone().mult(-0.5d));

      result = new SumResult<T>(count, targetSum);
    } else {
      T emptyTarget = (T) _bins.first().getTarget().init();
      Bin<T> bin_i = _bins.floor(p);
      if (bin_i == null) {
        bin_i = new Bin<T>(_minimum, 0, (T) emptyTarget.clone());
      }
      
      Bin<T> bin_i1 = _bins.higher(p);
      if (bin_i1 == null) {
        bin_i1 = new Bin<T>(_maximum, 0, (T) emptyTarget.clone());
      }

      double prevCount;
      T prevTargetSum;
      if (bin_i.getMean() == _minimum) {
        prevCount = _bins.first().getCount() / 2;
        prevTargetSum = (T) _bins.first().getTarget().clone().mult(0.5);
      } else {
        SumResult<T> prevSumResult = getPointToSumMap().get(bin_i.getMean());
        prevCount = prevSumResult.getCount();
        prevTargetSum = prevSumResult.getTargetSum();
      }

      double bDiff = p - bin_i.getMean();
      double pDiff = bin_i1.getMean() - bin_i.getMean();
      double bpRatio = bDiff / pDiff;

      NumericTarget countTarget = (NumericTarget) computeSum(bpRatio, new NumericTarget(prevCount),
              new NumericTarget(bin_i.getCount()), new NumericTarget(bin_i1.getCount()));
      double countSum = countTarget.getSum();

      T targetSum = (T) computeSum(bpRatio, prevTargetSum, bin_i.getTarget(), bin_i1.getTarget());

      result = new SumResult<T>(countSum, targetSum);
    }

    return result;
  }