public double logDensity(double value) {

    // Update boundaries if necessary
    updateBoundariesAndOrWeights();

    if (m_Boundaries == null) {
      return Math.log(Double.MIN_VALUE);
    }

    // Find the bin
    int index = Arrays.binarySearch(m_Boundaries, value);

    // Is the value outside?
    if ((index == -1) || (index == -m_Boundaries.length - 1)) {

      // Use normal density outside
      double val = 0;
      if (index == -1) { // Smaller than minimum
        val = m_TM.firstKey() - value;
      } else {
        val = value - m_TM.lastKey();
      }
      return (CONST - Math.log(m_Width) - 0.5 * (val * val / (m_Width * m_Width))) -
        Math.log(m_SumOfWeights + 2); 
    }
    
    // Is value exactly equal to right-most boundary?
    if (index == m_Boundaries.length - 1) {
      index--;
    } else {

      // Need to reverse index if necessary
      if (index < 0) {
        index = -index - 2;
      }
    }
    
    // Figure out of width
    double width = m_Boundaries[index + 1] - m_Boundaries[index];

    // Density compontent from smeared-out data point
    double densSmearedOut = 1.0 / ((m_SumOfWeights + 2) * (m_Boundaries[m_Boundaries.length - 1] -
                                                           m_Boundaries[0]));

    // Return log of density
    if (m_Weights[index] <= 0) {

      /*      System.out.println(value);
      System.out.println(this);
      System.exit(1);*/
      // Just use one smeared-out data point
      return Math.log(densSmearedOut);
    } else {
      return Math.log(densSmearedOut + m_Weights[index] / ((m_SumOfWeights + 2) * width));
    }
  }