public bool Equals(NumericalValue <T> other)
        {
            var enumerateThis  = ranges.GetEnumerator();
            var enumerateOther = other.ranges.GetEnumerator();

            while (true)
            {
                if (enumerateThis.MoveNext())
                {
                    if (enumerateOther.MoveNext())
                    {
                        if (!enumerateThis.Current.Equals(enumerateOther.Current))
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    if (enumerateOther.MoveNext())
                    {
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
            }
        }
        /*
         * private class Range
         * {
         *  public MinPair min;
         *  public MaxPair max;
         *
         *  public Range(MinPair min, MaxPair max)
         *  {
         *      this.min = min;
         *      this.max = max;
         *  }
         * }
         *
         * private class MinPair
         * {
         *  T value;
         *  Inclusivity inclusivity;
         *
         *  public MinPair(T value, Inclusivity inclusivity)
         *  {
         *      this.value = value;
         *      this.inclusivity = inclusivity;
         *  }
         *
         *  public static bool operator==(MinPair self, MinPair other)
         *  {
         *      return self.value == other.value && self.inclusivity == other.inclusivity;
         *  }
         *  public static bool operator!=(MinPair self, MinPair other) { return self != other; }
         * }
         *
         * private class MaxPair
         * {
         *  T value;
         *  Inclusivity inclusivity;
         *
         *  public MaxPair(T value, Inclusivity inclusivity)
         *  {
         *      this.value = value;
         *      this.inclusivity = inclusivity;
         *  }
         * }
         */

        public void UnionWith(NumericalValue <T> other)
        {
            foreach (Range n in other.ranges)
            {
                UnionWith(n);
            }
        }
        public void IntersectWith(NumericalValue <T> other)
        {
            NumericalValue <T> output = new NumericalValue <T>();

            foreach (var r in other.ranges)
            {
                NumericalValue <T> c = this.Clone();
                c.IntersectWith(r);
                output.UnionWith(c);
            }
            this.ranges = output.ranges;
        }
 public void AssignValue(NumericalValue <T> other)
 {
     this.ranges = new SortedSet <Range>(other.ranges);
 }
        private void analyze(ControlFlowGraph graph, SyntaxNode node, Dictionary <string, NumericalValue <int> > variables, Dictionary <SyntaxNode, Dictionary <string, NumericalValue <int> > > history)
        {
            #region Union usagesAfter with reachingDefinitions
            if (history.ContainsKey(node))
            {
                bool anyChanged = false;
                foreach (var pair in history[node])
                {
                    if (variables.ContainsKey(pair.Key))
                    {
                        var    i   = variables[pair.Key];
                        string old = i.ToString();
                        //Console.WriteLine("{0} vs {1} and {2}", old, i, pair.Value);
                        i.UnionWith(pair.Value);
                        if (!old.Equals(i.ToString()))
                        {
                            anyChanged = true;
                        }
                    }
                    else
                    {
                        variables.Add(pair.Key, pair.Value.Clone());
                        anyChanged = true;
                    }
                }
                if (history[node].Count == 0 && variables.Count != 0)
                {
                    anyChanged = true;
                }
                if (!anyChanged)
                {
                    return;
                }
                else
                {
                    var clone = new Dictionary <string, NumericalValue <int> >();
                    foreach (var v in variables)
                    {
                        clone.Add(v.Key, v.Value.Clone());
                    }
                    history[node] = clone;
                }
            }
            else
            {
                var clone = new Dictionary <string, NumericalValue <int> >();
                foreach (var v in variables)
                {
                    clone.Add(v.Key, v.Value.Clone());
                }
                history.Add(node, clone);
            }
            #endregion

            NumericalValue <int> rangeTrue  = null;
            NumericalValue <int> rangeFalse = null;
            string rangeVar = null;

            #region Process node
            if (node is LocalDeclarationStatementSyntax || node is VariableDeclarationSyntax)
            {
                VariableDeclarationSyntax s;
                if (node is LocalDeclarationStatementSyntax)
                {
                    s = (node as LocalDeclarationStatementSyntax).Declaration;
                }
                else
                {
                    s = node as VariableDeclarationSyntax;
                }

                foreach (var v in s.Variables)
                {
                    if (v.Initializer != null)
                    {
                        if (v.Initializer.Value is LiteralExpressionSyntax)
                        {
                            var valS = (v.Initializer.Value as LiteralExpressionSyntax).Token.ValueText;
                            int valI;
                            if (int.TryParse(valS, out valI))
                            {
                                var valNV = new NumericalValue <int>(valI);
                                if (variables.ContainsKey(v.Identifier.ToString()))
                                {
                                    variables[v.Identifier.ToString()].AssignValue(valNV);
                                }
                                else
                                {
                                    variables.Add(v.Identifier.ToString(), valNV);
                                }
                            }
                        }
                        else if (v.Initializer.Value is IdentifierNameSyntax)
                        {
                            var valNV = variables[v.Initializer.Value.ToString()];
                            if (variables.ContainsKey(v.Identifier.ToString()))
                            {
                                variables[v.Identifier.ToString()].AssignValue(valNV);
                            }
                            else
                            {
                                variables.Add(v.Identifier.ToString(), valNV);
                            }
                        }
                        else
                        {
                            var valNV = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE);
                            if (variables.ContainsKey(v.Identifier.ToString()))
                            {
                                variables[v.Identifier.ToString()].AssignValue(valNV);
                            }
                            else
                            {
                                variables.Add(v.Identifier.ToString(), valNV);
                            }
                        }
                    }
                }
            }
            else if (node is ExpressionStatementSyntax && (node as ExpressionStatementSyntax).Expression is AssignmentExpressionSyntax)
            {
                var s = (node as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax;
                if (s.Right is LiteralExpressionSyntax)
                {
                    var valS = (s.Right as LiteralExpressionSyntax).Token.ValueText;
                    int valI;
                    if (int.TryParse(valS, out valI))
                    {
                        var valNV = new NumericalValue <int>(valI);
                        if (variables.ContainsKey(s.Left.ToString()))
                        {
                            variables[s.Left.ToString()].AssignValue(valNV);
                        }
                        else
                        {
                            variables.Add(s.Left.ToString(), valNV);
                        }
                    }
                }
                else if (s.Right is IdentifierNameSyntax)
                {
                    var valNV = variables[s.Right.ToString()];
                    if (variables.ContainsKey(s.Left.ToString()))
                    {
                        variables[s.Left.ToString()].AssignValue(valNV);
                    }
                    else
                    {
                        variables.Add(s.Left.ToString(), valNV);
                    }
                }
                else
                {
                    var valNV = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE);
                    if (variables.ContainsKey(s.Left.ToString()))
                    {
                        variables[s.Left.ToString()].AssignValue(valNV);
                    }
                    else
                    {
                        variables.Add(s.Left.ToString(), valNV);
                    }
                }
            }
            else if (node is BinaryExpressionSyntax)
            {
                var n = node as BinaryExpressionSyntax;
                if (n.Right is LiteralExpressionSyntax)
                {
                    int value;
                    if (int.TryParse((n.Right as LiteralExpressionSyntax).Token.ValueText, out value))
                    {
                        if (n.OperatorToken.ToString().Equals("<"))
                        {
                            rangeTrue  = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.EXCLUSIVE);
                            rangeFalse = new NumericalValue <int>(value, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE);
                            rangeVar   = n.Left.ToString();
                        }
                        if (n.OperatorToken.ToString().Equals("<="))
                        {
                            rangeTrue  = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.INCLUSIVE);
                            rangeFalse = new NumericalValue <int>(value, Inclusivity.EXCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE);
                            rangeVar   = n.Left.ToString();
                        }
                        if (n.OperatorToken.ToString().Equals(">"))
                        {
                            rangeTrue  = new NumericalValue <int>(value, Inclusivity.EXCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE);
                            rangeFalse = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.INCLUSIVE);
                            rangeVar   = n.Left.ToString();
                        }
                        if (n.OperatorToken.ToString().Equals(">="))
                        {
                            rangeTrue  = new NumericalValue <int>(value, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE);
                            rangeFalse = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.EXCLUSIVE);
                            rangeVar   = n.Left.ToString();
                        }
                    }
                }
            }

            if (debug)
            {
                Console.WriteLine("({0}): {1} {2}", node.GetLocation().GetLineSpan().StartLinePosition, node, node.GetType());
                foreach (var pair in variables)
                {
                    Console.WriteLine("  {0} -> {1}", pair.Key, pair.Value);
                }
            }
            #endregion

            #region Recurse
            foreach (var succ in graph.GetSuccessorsB(node))
            {
                var variablesPrime = new Dictionary <string, NumericalValue <int> >();
                foreach (var v in variables)
                {
                    variablesPrime.Add(v.Key, v.Value.Clone());
                }
                if (succ.Value == 0)
                {
                    variablesPrime[rangeVar].IntersectWith(rangeFalse);
                }
                else if (succ.Value == 1)
                {
                    variablesPrime[rangeVar].IntersectWith(rangeTrue);
                }
                analyze(graph, succ.Key, variablesPrime, history);
            }
            #endregion
        }