Program: 117180
Project: 117180
Buggy source:
protected static void split(List<Double> uniqueValues,List<DoublePair> stats,Interval parent,double limit){
  if (parent.weight <= limit || parent.end - parent.start <= 1) {
    parent.split=Double.NaN;
  }
 else {
    parent.left=new Interval();
    parent.right=new Interval();
    int start=parent.left.start=parent.start;
    int end=parent.right.end=parent.end;
    final double totalWeight=parent.weight;
    final double sum=parent.sum;
    double weight1=stats.get(start).v1;
    double weight2=totalWeight - weight1;
    double sum1=stats.get(start).v2;
    double sum2=sum - sum1;
    double bestEval=-sum1 * sum1 / weight1 - sum2 * sum2 / weight2;
    List<double[]> splits=new ArrayList<>();
    splits.add(new double[]{(uniqueValues.get(start) + uniqueValues.get(start + 1)) / 2,start,weight1,sum1,weight2,sum2});
    for (int i=start + 1; i < end - 1; i++) {
      final double w=stats.get(i).v1;
      final double s=stats.get(i).v2;
      weight1+=w;
      weight2-=w;
      sum1+=s;
      sum2-=s;
      double eval=-sum1 * sum1 / weight1 - sum2 * sum2 / weight2;
      if (eval <= bestEval) {
        double split=(uniqueValues.get(i) + uniqueValues.get(i + 1)) / 2;
        if (eval < bestEval) {
          bestEval=eval;
          splits.clear();
        }
        splits.add(new double[]{split,i,weight1,sum1,weight2,sum2});
      }
    }
    Random rand=Random.getInstance();
    double[] split=splits.get(rand.nextInt(splits.size()));
    parent.split=split[0];
    parent.left.end=(int)split[1] + 1;
    parent.right.start=(int)split[1] + 1;
    parent.left.weight=split[2];
    parent.left.sum=split[3];
    parent.right.weight=split[4];
    parent.right.sum=split[5];
    parent.gain=(split[3] / split[2]) * split[3] + (split[5] / split[4]) * split[5];
    parent.value=-parent.gain + (sum / totalWeight * sum);
  }
}

Fixed version (ground truth):
protected static void split(List<Double> uniqueValues,List<DoublePair> stats,Interval parent,double limit){
  if (parent.weight <= limit || parent.end - parent.start <= 1) {
    parent.split=Double.NaN;
  }
 else {
    parent.left=new Interval();
    parent.right=new Interval();
    int start=parent.left.start=parent.start;
    int end=parent.right.end=parent.end;
    final double totalWeight=parent.weight;
    final double sum=parent.sum;
    double weight1=stats.get(start).v1;
    double weight2=totalWeight - weight1;
    double sum1=stats.get(start).v2;
    double sum2=sum - sum1;
    double bestEval=-(OptimUtils.getGain(sum1,weight1) + OptimUtils.getGain(sum2,weight2));
    List<double[]> splits=new ArrayList<>();
    splits.add(new double[]{(uniqueValues.get(start) + uniqueValues.get(start + 1)) / 2,start,weight1,sum1,weight2,sum2});
    for (int i=start + 1; i < end - 1; i++) {
      final double w=stats.get(i).v1;
      final double s=stats.get(i).v2;
      weight1+=w;
      weight2-=w;
      sum1+=s;
      sum2-=s;
      double eval1=OptimUtils.getGain(sum1,weight1);
      double eval2=OptimUtils.getGain(sum2,weight2);
      double eval=-(eval1 + eval2);
      if (eval <= bestEval) {
        double split=(uniqueValues.get(i) + uniqueValues.get(i + 1)) / 2;
        if (eval < bestEval) {
          bestEval=eval;
          splits.clear();
        }
        splits.add(new double[]{split,i,weight1,sum1,weight2,sum2});
      }
    }
    Random rand=Random.getInstance();
    double[] split=splits.get(rand.nextInt(splits.size()));
    parent.split=split[0];
    parent.left.end=(int)split[1] + 1;
    parent.right.start=(int)split[1] + 1;
    parent.left.weight=split[2];
    parent.left.sum=split[3];
    parent.right.weight=split[4];
    parent.right.sum=split[5];
    parent.gain=(split[3] / split[2]) * split[3] + (split[5] / split[4]) * split[5];
    parent.value=-parent.gain + (sum / totalWeight * sum);
  }
}