std::vector< std::vector<int> > datastructures::TarjansAlgorithm::getSCCs(std::vector<varset> &parents) {
    initChildMatrix(parents);
    
    for (int i = 0; i < indices.size(); i++) {
        indices[i] = -1;
    }
    stronglyConnectedComponents.clear();
    
    /**
    * index := 0 S := empty for each v in V do if (v.index is undefined)
    * then strongconnect(v) end if repeat
    */
   index = 0;
   while (S.size() > 0) {
       S.pop();
   }

   for (int v = 0; v < size; v++) {
       if (indices[v] == -1) {
           strongconnect(v);
       }
   }
    
    return stronglyConnectedComponents;
}
void datastructures::TarjansAlgorithm::strongconnect(int v) {
    /**
         * Set the depth index for v to the smallest unused index
         *
         * v.index := index v.lowlink := index index := index + 1 S.push(v)
         *
         */
        indices[v] = index;
        lowlink[v] = index;
        index++;
        S.push(v);
        VARSET_SET(sContents, v);

        /**
         * Consider successors of v
         *
         * for each (v, w) in E do if (w.index is undefined) then // Successor w
         * has not yet been visited; recurse on it strongconnect(w) v.lowlink :=
         * min(v.lowlink, w.lowlink) else if (w is in S) then // Successor w is
         * in stack S and hence in the current SCC v.lowlink := min(v.lowlink,
         * w.index) end if repeat
         *
         */
        for (int w = 0; w < size; w++) {
            if (! VARSET_GET(childMatrix[v], w)) continue;
            
            if (indices[w] == -1) {
                strongconnect(w);
                int mi = std::min(lowlink[v], lowlink[w]);
                lowlink[v] = mi;
            } else if (VARSET_GET(sContents, w)) {
                int mi = std::min(lowlink[v], indices[w]);
                lowlink[v] = mi;
            }
        }

        /**
         * If v is a root node, pop the stack and generate an SCC
         *
         * if (v.lowlink = v.index) then start a new strongly connected
         * component repeat w := S.pop() add w to current strongly connected
         * component until (w = v) output the current strongly connected
         * component end if
         *
         */
        if (lowlink[v] == indices[v]) {
            std::vector<int> scc;
            int w = -1;
            do {
                w = S.top();
                S.pop();
                VARSET_CLEAR(sContents, w);
                scc.push_back(w);
            } while (w != v);

            stronglyConnectedComponents.push_back(scc);
        }
}
// Node v is the i-the node
// Graph is passed to use getOutgoingEdges
void StronglyConnectedComponentsVisitor::strongconnect(Graph* g, Node *v, int i)
{
    // Set the depth index for v to the smallest unused index
    _indexTable[i] = _index;
    _lowlinkTable[i] = _index;
    _index = _index +1;
    S.push_front(v);

    list<Edge*> outgoing = g->getOutgoingEdges(v);
    // Consider successors of v
    // For each (v, w) in E
    for (list<Edge*>::iterator it = outgoing.begin() ; it != outgoing.end(); ++it)
    {
        // current w
        Node* w = (*it)->getTarget();
        // if w's index is undefined
        if ( _indexTable[g->nodeToIndex(w)] == -1)
        {
            // Successor w has not yet been visited; recurse on it
            strongconnect(g, w, g->nodeToIndex(w));
            // v.lowlink := min(v.lowlink, w.lowlink)
            _lowlinkTable[g->nodeToIndex(v)] = min( _lowlinkTable[g->nodeToIndex(v)], _lowlinkTable[g->nodeToIndex(w)] );
        }
        // else if ( w is in S )
        else if ( isInStack(w) )
        {
            // Successor w is in stack S and hence in the current SCC
            // v.lowlink := min(v.lowlink, w.index)
            _lowlinkTable[g->nodeToIndex(v)] = min(_lowlinkTable[g->nodeToIndex(v)], _indexTable[g->nodeToIndex(w)] );
        }
    }

    // If v is a root node, pop the stack and generate a SCC
    if (_lowlinkTable[g->nodeToIndex(v)] == _indexTable[g->nodeToIndex(v)])
    {
        Node * w;
        // start a new strongly connected component
        vector<Node*> scc;
        do
        {
            w = S.front();
            S.pop_front();
            // add w to current strongly connected component
            scc.push_back(w);
        } while (!(w==v));

        // add the current strongly connected component to the vector of strongly connected component
        _SCC.push_back(scc);
    }

}
  static void
  scc(CallGraphWrapperPass &cg, RecursiveGuardSpecPolicy::SCC& scc)
  {
    std::map<const Function*, std::pair<int, int> > indicies;
    std::list<Function*> stack;
    std::set<Function*> stack_contents;
    int index = 0;

    for (CallGraphWrapperPass::iterator i = cg.begin(), e = cg.end(); i != e; ++i) {
      if (indicies.find(i->first) == indicies.end()) {
        strongconnect(i->second, cg, stack, stack_contents, indicies, index, scc);
      }
    }
  }
  static void
  strongconnect(CallGraphNode* from, CallGraphWrapperPass& cg,
      std::list<Function*>& stack, std::set<Function*>& stack_contents,
      std::map<const Function*, std::pair<int, int> >& indicies, int& next_idx,
      RecursiveGuardSpecPolicy::SCC& result)
  {
    int base_idx = next_idx;
    Function* f = from->getFunction();
    indicies[f] = std::pair<int, int>(next_idx, next_idx);
    next_idx++;
    stack.push_back(f);

    bool self = false;

    for (CallGraphNode::iterator i = from->begin(), e = from->end(); i != e; ++i) {
      Function* fi = i->second->getFunction();
      if (fi == NULL) continue;
      if (fi == f) self = true;
      if (indicies.find(fi) == indicies.end()) {
        strongconnect(i->second, cg, stack, stack_contents, indicies, next_idx, result);
        std::pair<int,int>& wi = indicies[fi];
        std::pair<int,int>& vi = indicies[f];
        vi.second = std::min(vi.second, wi.second);
      } else if (stack_contents.find(fi) != stack_contents.end()) {
        std::pair<int,int>& wi = indicies[fi];
        std::pair<int,int>& vi = indicies[f];
        vi.second = std::min(vi.second, wi.first);
      }
    }

    std::pair<int,int>& vi = indicies[f];
    if (vi.first == vi.second) {
      if (stack.back() == f && !self) {
        stack.pop_back();
        return;
      }
      Function* w = NULL;
      do {
        w = stack.back();
        stack.pop_back();
        result[w] = base_idx;
      } while (w != f);
    }
  }
void StronglyConnectedComponentsVisitor::computeComponents(Graph & graph, bool color)
{
    // reset _SCC
    _SCC.clear();

    vector<Node*> nodes = graph.getNodes();
    int size = nodes.size();

    initTables(size);

    for ( int i = 0; i < size; ++i )
    {
        // if nodes[i] has no index
        if ( _indexTable[i] == -1 )
            strongconnect( &graph, nodes[i], i );
    }

    if ( color )
    // color the different strongly connected components to distinguish them
        colorComponents();
}