Exemple #1
0
 /// <summary>
 /// Recursively assigns range outputs to each node.
 /// </summary>
 internal void AddOutputs(int index, Int64Range 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);
     }
 }
Exemple #2
0
        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);
        }