protected void updateBoundariesAndWeights() {

    // Get values and keys from tree map
    double[] values = new double[m_TM.size()];
    double[] weights = new double[m_TM.size()];
    Iterator<Map.Entry<Double,Double>> itr = m_TM.entrySet().iterator();
    int j = 0;
    while(itr.hasNext()) {
      Map.Entry<Double,Double> entry = itr.next();
      values[j] = entry.getKey();
      weights[j] = entry.getValue();
      j++;
    }

    double freq = m_SumOfWeights / m_NumBins;
    double[] cutPoints = new double[m_NumBins - 1];
    double[] binWeights = new double[m_NumBins];
    double sumOfWeights = m_SumOfWeights;

    // Compute break points
    double weightSumSoFar = 0, lastWeightSum = 0;
    int cpindex = 0, lastIndex = -1;
    for (int i = 0; i < values.length - 1; i++) {

      // Update weight statistics
      weightSumSoFar += weights[i];
      sumOfWeights -= weights[i];

      // Have we passed the ideal size?
      if (weightSumSoFar >= freq) {

        // Is this break point worse than the last one?
        if (((freq - lastWeightSum) < (weightSumSoFar - freq)) && (lastIndex != -1)) {
          cutPoints[cpindex] = (values[lastIndex] + values[lastIndex + 1]) / 2;
          weightSumSoFar -= lastWeightSum;
          binWeights[cpindex] = lastWeightSum;
          lastWeightSum = weightSumSoFar;
          lastIndex = i;
        } else {
          cutPoints[cpindex] = (values[i] + values[i + 1]) / 2;
          binWeights[cpindex] = weightSumSoFar;
          weightSumSoFar = 0;
          lastWeightSum = 0;
          lastIndex = -1;
        }
        cpindex++;
        freq = (sumOfWeights + weightSumSoFar) / ((cutPoints.length + 1) - cpindex);
      } else {
        lastIndex = i;
        lastWeightSum = weightSumSoFar;
      }
    }

    // Check whether there was another possibility for a cut point
    if ((cpindex < cutPoints.length) && (lastIndex != -1)) {
      cutPoints[cpindex] = (values[lastIndex] + values[lastIndex + 1]) / 2;      
      binWeights[cpindex] = lastWeightSum;
      cpindex++;
      binWeights[cpindex] = weightSumSoFar - lastWeightSum;
    } else {
      binWeights[cpindex] = weightSumSoFar;
    }

    // Did we find any cutpoints?
    if (cpindex == 0) {
      m_Boundaries = null;
      m_Weights = null;
    } else {

      // Need to add weight of last data point to right-most bin
      binWeights[cpindex] += weights[values.length - 1];

      // Copy over boundaries and weights
      m_Boundaries = new double[cpindex + 2];
      m_Boundaries[0] = m_TM.firstKey();
      m_Boundaries[cpindex + 1] = m_TM.lastKey();
      System.arraycopy(cutPoints, 0, m_Boundaries, 1, cpindex);
      m_Weights = new double[cpindex + 1];
      System.arraycopy(binWeights, 0, m_Weights, 0, cpindex + 1);
    }
  }