code: private int computeRequiredBufferNum(int numChildNodes, int combineDegree)
    {
      // numChildrenForLastNode used to determine that the last node is needed for the current level.
      // Please see buildCombineTree() for more details.
      final int numChildrenForLastNode = numChildNodes % combineDegree;
      final int numCurLevelNodes = numChildNodes / combineDegree + (numChildrenForLastNode > 1 ? 1 : 0);
      final int numChildOfParentNodes = numCurLevelNodes + (numChildrenForLastNode == 1 ? 1 : 0);
  
      if (numChildOfParentNodes == 1) {
        return numCurLevelNodes;
      } else {
        return numCurLevelNodes +
               computeRequiredBufferNum(numChildOfParentNodes, intermediateCombineDegree);
      }
    }
docs: Recursively compute the number of required buffers for a combining tree in a bottom-up manner.  Since each node of
  the combining tree represents a combining task and each combining task requires one buffer, the number of required
  buffers is the number of nodes of the combining tree.
  
  @param numChildNodes number of child nodes
  @param combineDegree combine degree for the current level
  
  @return minimum number of buffers required for combining tree
  
  @see #buildCombineTree