docs: @Override
    protected HashMap<String, Object> getDistribution(String argument) {
      HashMap<String, Object> result = new LinkedHashMap<>();
      Double start = null;
      Double end = null;
      Double step = null;
      Integer d = null;
      Integer number = null;
      if (argument != null) {
        Matcher m = fpArgument.matcher(argument);
        // get settings
        while (m.find()) {
          if (m.group(1).trim().equals("start")) {
            start = Double.parseDouble(m.group(2));
            d = (d == null) ? getNumberOfDecimals(m.group(2))
                : Math.max(d, getNumberOfDecimals(m.group(2)));
          } else if (m.group(1).trim().equals("end")) {
            end = Double.parseDouble(m.group(2));
            d = (d == null) ? getNumberOfDecimals(m.group(2))
                : Math.max(d, getNumberOfDecimals(m.group(2)));
          } else if (m.group(1).trim().equals("step")) {
            step = Double.parseDouble(m.group(2));
            d = (d == null) ? getNumberOfDecimals(m.group(2))
                : Math.max(d, getNumberOfDecimals(m.group(2)));
          } else if (m.group(1).trim().equals("number")) {
            number = Integer.parseInt(m.group(2));
          }
        }
      }
      // always exactly one of (positive) number and (positive) step, other null
      if ((number == null || number < 1) && (step == null || step <= 0)) {
        number = 10;
        step = null;
      } else if (step != null && step <= 0) {
        step = null;
      } else if (number != null && number < 1) {
        number = null;
      } else if (step != null) {
        number = null;
      }
      // sanity checks start/end
      createStats();
      double tmpStart = stats.getMin();
      double tmpEnd = stats.getMax();
      if (start != null && end != null && start > end) {
        return null;
      } else if (start != null && start > tmpEnd) {
        return null;
      } else if (end != null && end < tmpStart) {
        return null;
      }
      // check start and end
      if (start == null && end == null) {
        if (step == null) {
          step = (tmpEnd - tmpStart) / number;
        }
        number = Double.valueOf(Math.ceil((tmpEnd - tmpStart) / step)).intValue();
        start = tmpStart;
        end = start + (number * step);
      } else if (start == null) {
        if (step == null) {
          step = (end - tmpStart) / number;
        }
        number = Double.valueOf(Math.ceil((end - tmpStart) / step)).intValue();
        start = end - (number * step);
      } else if (end == null) {
        if (step == null) {
          step = (tmpEnd - start) / number;
        }
        number = Double.valueOf(Math.ceil((tmpEnd - start) / step)).intValue();
        end = start + (number * step);
      } else {
        if (step == null) {
          step = (end - start) / number;
        }
        number = Double.valueOf(Math.ceil((end - start) / step)).intValue();
      }
      // round step to agreeable format and recompute number
      int tmpD = Double.valueOf(Math.max(0, 1 + Math.ceil(-1 * Math.log10(step))))
          .intValue();
      d = (d == null) ? tmpD : Math.max(d, tmpD);
      double tmp = Math.pow(10.0, d);
      step = Math.round(step * tmp) / tmp;
      number = Double.valueOf(Math.ceil((end - start) / step)).intValue();
  
      // compute distribution
      long[] list = new long[number];
      for (Double v : fullValues) {
        if (v >= start && v <= end) {
          int i = Math.min(
              Double.valueOf(Math.floor((v - start) / step)).intValue(),
              (number - 1));
          list[i]++;
        }
      }
      Double l;
      Double r;
      String ls;
      String lsFormat;
      String rs;
      String rsFormat;
      for (int i = 0; i < number; i++) {
        l = start + i * step;
        r = Math.min(end, l + step);
        lsFormat = "%." + d + "f";
        ls = String.format(lsFormat, l);
        rsFormat = "%." + d + "f";
        rs = String.format(rsFormat, r);
        String key = "[" + ls + "," + rs
            + ((i == (number - 1) && r >= tmpEnd && l <= tmpEnd) ? "]" : ")");
        result.put(key, list[i]);
      }
      return result;
    }