/// <summary> /// Recursively assigns range outputs to each node. </summary> internal void addOutputs(int index, LongRange range) { if (start >= range.minIncl && end <= range.maxIncl) { // Our range is fully included in the incoming // range; add to our output list: if (outputs == null) { outputs = new List <int?>(); } outputs.Add(index); } else if (left != null) { Debug.Assert(right != null); // Recurse: left.addOutputs(index, range); right.addOutputs(index, range); } }
public LongRangeCounter(LongRange[] 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?>(); endsMap[long.MinValue] = 1; endsMap[long.MaxValue] = 2; foreach (LongRange range in ranges) { int?cur; if (!endsMap.TryGetValue(range.minIncl, out 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].HasValue ? endsList[0].Value : 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].HasValue ? endsList[upto0].Value : 0; int flags = endsMap[v].HasValue ? endsMap[v].Value : 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 { Debug.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); }
public LongRangeCounter(LongRange[] 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?>(); endsMap[long.MinValue] = 1; endsMap[long.MaxValue] = 2; foreach (LongRange range in ranges) { int? cur; if (!endsMap.TryGetValue(range.minIncl,out 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].HasValue ? endsList[0].Value : 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].HasValue ? endsList[upto0].Value : 0; int flags = endsMap[v].HasValue ? endsMap[v].Value : 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 { Debug.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); }