public IncrementQueryObject Combine(IncrementQueryObject rightAdjacentObject) { var combinedQueryObject = new IncrementQueryObject(); combinedQueryObject.SubsumeRemainders(this); combinedQueryObject.SubsumeRemainders(rightAdjacentObject); return(combinedQueryObject); }
// Instead of returning the children object directly, we have to add on the parent's range addition. The // children query object knows the subset of the parent segment it intersects with, and everything in // there needs the additions that were applied to the parent segment as a whole. It's kind of weird, any // pending range additions specifically for the children object gets brought out and added to the sum when // we do .Combine or .Sum, but recursively it makes sense: the children object has a sum but still needs // to know about the parent's range additions. public IncrementQueryObject Query( int treeArrayIndex, int segmentStartIndex, int segmentEndIndex, int queryStartIndex, int queryEndIndex) { var parentQueryObject = _treeArray[treeArrayIndex]; if (queryStartIndex <= segmentStartIndex && queryEndIndex >= segmentEndIndex) { return(parentQueryObject); } int leftChildTreeArrayIndex = (treeArrayIndex << 1) | 1; int rightChildTreeArrayIndex = leftChildTreeArrayIndex + 1; int leftChildSegmentEndIndex = (segmentStartIndex + segmentEndIndex) >> 1; IncrementQueryObject childrenQueryObject; if (queryStartIndex <= leftChildSegmentEndIndex && queryEndIndex > leftChildSegmentEndIndex) { childrenQueryObject = Query( leftChildTreeArrayIndex, segmentStartIndex, leftChildSegmentEndIndex, queryStartIndex, queryEndIndex) .Combine(Query( rightChildTreeArrayIndex, leftChildSegmentEndIndex + 1, segmentEndIndex, queryStartIndex, queryEndIndex)); } else if (queryStartIndex <= leftChildSegmentEndIndex) { childrenQueryObject = Query( leftChildTreeArrayIndex, segmentStartIndex, leftChildSegmentEndIndex, queryStartIndex, queryEndIndex); } else { childrenQueryObject = Query( rightChildTreeArrayIndex, leftChildSegmentEndIndex + 1, segmentEndIndex, queryStartIndex, queryEndIndex); } var queryObject = new IncrementQueryObject { RangeIncrements = parentQueryObject.RangeIncrements }; queryObject.SubsumeRemainders(childrenQueryObject); return(queryObject); }