private int Rollup(Int64RangeNode node, int[] counts, bool sawOutputs) { int count; sawOutputs |= node.outputs != null; if (node.left != null) { count = Rollup(node.left, counts, sawOutputs); count += Rollup(node.right, counts, sawOutputs); } else { // Leaf: count = leafCounts[leafUpto]; leafUpto++; if (!sawOutputs) { // This is a missing count (no output ranges were // seen "above" us): missingCount += count; } } if (node.outputs != null) { foreach (int rangeIndex in node.outputs) { counts[rangeIndex] += count; } } //System.out.println(" rollup node=" + node.start + " to " + node.end + ": count=" + count); return(count); }
public Int64RangeNode(long start, long end, Int64RangeNode left, Int64RangeNode right, int leafIndex) { this.start = start; this.end = end; this.left = left; this.right = right; this.leafIndex = leafIndex; }
private static Int64RangeNode Split(int start, int end, IList <InclusiveRange> elementaryIntervals) { if (start == end - 1) { // leaf InclusiveRange range = elementaryIntervals[start]; return(new Int64RangeNode(range.Start, range.End, null, null, start)); } else { int mid = (int)((uint)(start + end) >> 1); Int64RangeNode left = Split(start, mid, elementaryIntervals); Int64RangeNode right = Split(mid, end, elementaryIntervals); return(new Int64RangeNode(left.start, right.end, left, right, -1)); } }
public Int64RangeCounter(Int64Range[] ranges) { // Maps all range inclusive endpoints to int flags; 1 // = start of interval, 2 = end of interval. We need to // track the start vs end case separately because if a // given point is both, then it must be its own // elementary interval: IDictionary <long?, int?> endsMap = new Dictionary <long?, int?> { [long.MinValue] = 1, [long.MaxValue] = 2 }; foreach (Int64Range range in ranges) { if (!endsMap.TryGetValue(range.minIncl, out int?cur)) { endsMap[range.minIncl] = 1; } else { endsMap[range.minIncl] = (int)cur | 1; } if (!endsMap.TryGetValue(range.maxIncl, out cur)) { endsMap[range.maxIncl] = 2; } else { endsMap[range.maxIncl] = (int)cur | 2; } } var endsList = new List <long?>(endsMap.Keys); endsList.Sort(); // Build elementaryIntervals (a 1D Venn diagram): IList <InclusiveRange> elementaryIntervals = new List <InclusiveRange>(); int upto0 = 1; long v = endsList[0] ?? 0; long prev; if (endsMap[v] == 3) { elementaryIntervals.Add(new InclusiveRange(v, v)); prev = v + 1; } else { prev = v; } while (upto0 < endsList.Count) { v = endsList[upto0] ?? 0; int flags = endsMap[v] ?? 0; //System.out.println(" v=" + v + " flags=" + flags); if (flags == 3) { // This point is both an end and a start; we need to // separate it: if (v > prev) { elementaryIntervals.Add(new InclusiveRange(prev, v - 1)); } elementaryIntervals.Add(new InclusiveRange(v, v)); prev = v + 1; } else if (flags == 1) { // This point is only the start of an interval; // attach it to next interval: if (v > prev) { elementaryIntervals.Add(new InclusiveRange(prev, v - 1)); } prev = v; } else { if (Debugging.AssertsEnabled) { Debugging.Assert(flags == 2); } // This point is only the end of an interval; attach // it to last interval: elementaryIntervals.Add(new InclusiveRange(prev, v)); prev = v + 1; } //System.out.println(" ints=" + elementaryIntervals); upto0++; } // Build binary tree on top of intervals: root = Split(0, elementaryIntervals.Count, elementaryIntervals); // Set outputs, so we know which range to output for // each node in the tree: for (int i = 0; i < ranges.Length; i++) { root.AddOutputs(i, ranges[i]); } // Set boundaries (ends of each elementary interval): boundaries = new long[elementaryIntervals.Count]; for (int i = 0; i < boundaries.Length; i++) { boundaries[i] = elementaryIntervals[i].End; } leafCounts = new int[boundaries.Length]; //System.out.println("ranges: " + Arrays.toString(ranges)); //System.out.println("intervals: " + elementaryIntervals); //System.out.println("boundaries: " + Arrays.toString(boundaries)); //System.out.println("root:\n" + root); }