docs: private void downwardChartPass(CfgParseChart chart) {
      Preconditions.checkState(chart.getInsideCalculated());
  
      // Calculate root marginal, which is not included in the rest of the pass.
      // Also compute the partition function.
      Factor rootOutside = chart.getOutsideEntries(0, chart.chartSize() - 1);
      Factor rootInside = chart.getInsideEntries(0, chart.chartSize() - 1);
      Factor rootMarginal = rootOutside.product(rootInside);
      chart.setPartitionFunction(rootMarginal.marginalize(parentVar).getUnnormalizedProbability(
          Assignment.EMPTY));
  
      double[] newValues = new double[binaryDistributionWeights.getValues().length];
      for (int spanSize = chart.chartSize() - 1; spanSize >= 1; spanSize--) {
        for (int spanStart = 0; spanStart + spanSize < chart.chartSize(); spanStart++) {
          int spanEnd = spanStart + spanSize;
          calculateOutside(spanStart, spanEnd, chart, newValues);
        }
      }
      updateTerminalRuleCounts(chart);
  
      // Outside probabilities / partition function are now calculated.
      chart.setOutsideCalculated();
    }