docs: public void splitNode(KDTreeNode node, int numNodesCreated,
        double[][] nodeRanges, double[][] universe) throws Exception {
  
      correctlyInitialized();
  
      int splitDim = -1;
      double splitVal = Double.NEGATIVE_INFINITY;
  
      double leftAttSum[] = new double[m_Instances.numAttributes()], 
             rightAttSum[] = new double[m_Instances.numAttributes()], 
             leftAttSqSum[] = new double[m_Instances.numAttributes()], 
             rightAttSqSum[] = new double[m_Instances.numAttributes()], 
             rightSqMean, leftSqMean, leftSqSum, rightSqSum, 
             minSum = Double.POSITIVE_INFINITY, val;
  
      for (int dim = 0; dim < m_Instances.numAttributes(); dim++) {
        // m_MaxRelativeWidth in KDTree ensure there'll be atleast one dim with
        // width > 0.0
        if (node.m_NodeRanges[dim][WIDTH] == 0.0
            || dim == m_Instances.classIndex())
          continue;
  
        quickSort(m_Instances, m_InstList, dim, node.m_Start, node.m_End);
  
        for (int i = node.m_Start; i <= node.m_End; i++) {
          for (int j = 0; j < m_Instances.numAttributes(); j++) {
            if (j == m_Instances.classIndex())
              continue;
            val = m_Instances.instance(m_InstList[i]).value(j);
            if (m_NormalizeNodeWidth) {
              if (Double.isNaN(universe[j][MIN])
                  || universe[j][MIN] == universe[j][MAX])
                val = 0.0;
              else
                val = ((val - universe[j][MIN]) / universe[j][WIDTH]); // normalizing
                                                                        // value
            }
            if (i == node.m_Start) {
              leftAttSum[j] = rightAttSum[j] = leftAttSqSum[j] = rightAttSqSum[j] = 0.0;
            }
            rightAttSum[j] += val;
            rightAttSqSum[j] += val * val;
          }
        }
  
        for (int i = node.m_Start; i <= node.m_End - 1; i++) {
          Instance inst = m_Instances.instance(m_InstList[i]);
          leftSqSum = rightSqSum = 0.0;
          for (int j = 0; j < m_Instances.numAttributes(); j++) {
            if (j == m_Instances.classIndex())
              continue;
            val = inst.value(j);
  
            if (m_NormalizeNodeWidth) {
              if (Double.isNaN(universe[j][MIN])
                  || universe[j][MIN] == universe[j][MAX])
                val = 0.0;
              else
                val = ((val - universe[j][MIN]) / universe[j][WIDTH]); // normalizing
                                                                        // value
            }
  
            leftAttSum[j] += val;
            rightAttSum[j] -= val;
            leftAttSqSum[j] += val * val;
            rightAttSqSum[j] -= val * val;
            leftSqMean = leftAttSum[j] / (i - node.m_Start + 1);
            leftSqMean *= leftSqMean;
            rightSqMean = rightAttSum[j] / (node.m_End - i);
            rightSqMean *= rightSqMean;
  
            leftSqSum += leftAttSqSum[j] - (i - node.m_Start + 1) * leftSqMean;
            rightSqSum += rightAttSqSum[j] - (node.m_End - i) * rightSqMean;
          }
  
          if (minSum > (leftSqSum + rightSqSum)) {
            minSum = leftSqSum + rightSqSum;
  
            if (i < node.m_End)
              splitVal = (m_Instances.instance(m_InstList[i]).value(dim) + m_Instances
                  .instance(m_InstList[i + 1]).value(dim)) / 2;
            else
              splitVal = m_Instances.instance(m_InstList[i]).value(dim);
  
            splitDim = dim;
          }
        }// end for instance i
      }// end for attribute dim
  
      int rightStart = rearrangePoints(m_InstList, node.m_Start, node.m_End,
          splitDim, splitVal);
  
      if (rightStart == node.m_Start || rightStart > node.m_End) {
        System.out.println("node.m_Start: " + node.m_Start + " node.m_End: "
            + node.m_End + " splitDim: " + splitDim + " splitVal: " + splitVal
            + " node.min: " + node.m_NodeRanges[splitDim][MIN] + " node.max: "
            + node.m_NodeRanges[splitDim][MAX] + " node.numInstances: "
            + node.numInstances());
  
        if (rightStart == node.m_Start)
          throw new Exception("Left child is empty in node " + node.m_NodeNumber
              + ". Not possible with "
              + "KMeanInspiredMethod splitting method. Please " + "check code.");
        else
          throw new Exception("Right child is empty in node " + node.m_NodeNumber
              + ". Not possible with "
              + "KMeansInspiredMethod splitting method. Please " + "check code.");
      }
  
      node.m_SplitDim = splitDim;
      node.m_SplitValue = splitVal;
      node.m_Left = new KDTreeNode(numNodesCreated + 1, node.m_Start,
          rightStart - 1, m_EuclideanDistance.initializeRanges(m_InstList,
              node.m_Start, rightStart - 1));
      node.m_Right = new KDTreeNode(numNodesCreated + 2, rightStart, node.m_End,
          m_EuclideanDistance
              .initializeRanges(m_InstList, rightStart, node.m_End));
    }