00001
00039
00040
00041 #include <iostream>
00042 using std::cout;
00043 #include <algorithm>
00044 #include <map>
00045 #include <list>
00046
00047 #ifdef NO_STD_CHEADERS
00048 # include <string.h>
00049 # include <stdio.h>
00050 # include <limits.h>
00051 #else
00052 # include <cstring>
00053 # include <cstdio>
00054 # include <climits>
00055 using namespace std;
00056 #endif
00057
00058 #include <unistd.h>
00059
00060
00061
00062 #include <OpenAnalysis/Utils/NestedSCR.hpp>
00063
00064
00065
00066 const OA::NestedSCR::DFNUM_t DFNUM_ROOT = 0;
00067 const OA::NestedSCR::DFNUM_t DFNUM_NIL = UINT_MAX;
00068
00069
00070
00071 namespace OA {
00072
00073
00074
00075
00076
00077
00078
00079 class TarjWork {
00080 public:
00081 TarjWork();
00082 ~TarjWork();
00083
00084 RIFG::NodeId wk_vertex;
00085 OA::NestedSCR::DFNUM_t wk_last;
00086 OA::NestedSCR::DFNUM_t wk_header;
00087 OA::NestedSCR::DFNUM_t wk_nextP;
00088 OA::NestedSCR::DFNUM_t wk_nextQ;
00089 bool wk_inP;
00090 bool wk_isCyclic;
00091 bool wk_reducible;
00092 std::list<int> backPreds;
00093 std::list<int> nonBackPreds;
00094 };
00095
00096
00097 TarjWork::TarjWork()
00098 {
00099 wk_vertex = RIFG::NIL;
00100 wk_last = DFNUM_NIL;
00101 wk_header = DFNUM_ROOT;
00102 wk_nextP = DFNUM_NIL;
00103 wk_nextQ = DFNUM_NIL;
00104 wk_inP = false;
00105 wk_isCyclic = false;
00106 wk_reducible = true;
00107 }
00108
00109
00110 TarjWork::~TarjWork()
00111 {
00112 backPreds.clear();
00113 nonBackPreds.clear();
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 class TarjTreeNode {
00128 public:
00129 TarjTreeNode();
00130 RIFG::NodeId nodeid;
00131 short level;
00132 NestedSCR::Node_t type;
00133 OA::NestedSCR::DFNUM_t outer;
00134 OA::NestedSCR::DFNUM_t inners;
00135 OA::NestedSCR::DFNUM_t next;
00136 int prenum;
00137 OA::NestedSCR::DFNUM_t last;
00138 RIFG::NodeId last_id;
00139 short loopIndex;
00140 };
00141
00142
00143 TarjTreeNode::TarjTreeNode()
00144 {
00145 nodeid = RIFG::NIL;
00146 level = 0;
00147 type = NestedSCR::NODE_ACYCLIC;
00148 outer = DFNUM_NIL;
00149 inners = DFNUM_NIL;
00150 next = DFNUM_NIL;
00151 prenum = -1;
00152 last = DFNUM_NIL;
00153 last_id = RIFG::NIL;
00154 loopIndex = -1;
00155 }
00156
00157 }
00158
00159
00160
00161
00162
00163
00164
00165 namespace OA {
00166
00167
00168 #define TARJ_nodeid(name) (tarj[name].nodeid)
00169 #define TARJ_outer(name) (tarj[name].outer)
00170 #define TARJ_inners(name) (tarj[name].inners)
00171 #define TARJ_next(name) (tarj[name].next)
00172 #define TARJ_level(name) (tarj[name].level)
00173 #define TARJ_type(name) (tarj[name].type)
00174 #define TARJ_last(name) (tarj[name].last)
00175 #define TARJ_last_id(name) (tarj[name].last_id)
00176 #define TARJ_loopIndex(name) (tarj[name].loopIndex)
00177 #define TARJ_contains(a,b) \
00178 ( ( tarj[a].prenum <= tarj[b].prenum ) && \
00179 ( tarj[b].prenum <= tarj[tarj[a].last].prenum ) \
00180 )
00181
00182
00183 #define vertex(x) (wk[x].wk_vertex)
00184 #define TLast(x) (wk[x].wk_last)
00185 #define header(x) (wk[x].wk_header)
00186 #define nextP(x) (wk[x].wk_nextP)
00187 #define nextQ(x) (wk[x].wk_nextQ)
00188 #define inP(x) (wk[x].wk_inP)
00189 #define isCyclic(x) (wk[x].wk_isCyclic)
00190 #define reducible(x) (wk[x].wk_reducible)
00191 #define backPreds(x) (wk[x].backPreds)
00192 #define nonBackPreds(x) (wk[x].nonBackPreds)
00193
00194 static int n;
00195 static int last_id;
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 #define is_backedge(a,b) ((b <= a) & (a <= TLast(b)))
00206
00207 #define dfnum(v) (nodeid_to_dfnum_map[v])
00208
00209
00210 NestedSCR::NestedSCR(OA::OA_ptr<OA::RIFG> rifg_)
00211 : rifg(rifg_)
00212 {
00213 Create();
00214 }
00215
00216
00217 NestedSCR::~NestedSCR()
00218 {
00219 if (tarj)
00220 delete[] tarj;
00221 if (uf)
00222 delete uf;
00223 if (wk)
00224 delete[] wk;
00225 rev_top_list.clear();
00226 nodeid_to_dfnum_map.clear();
00227 }
00228
00229
00230
00231 void
00232 NestedSCR::Create()
00233 {
00234 RIFG::NodeId root = rifg->getSource();
00235
00236 Init();
00237 DFS(root);
00238 FillPredLists();
00239 GetTarjans();
00240 Build();
00241 Sort();
00242 ComputeIntervalIndex();
00243 FreeWork();
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 void
00259 NestedSCR::Sort()
00260 {
00261 RIFG::NodeId gId;
00262 int parent;
00263
00264
00265
00266 OA_ptr<RIFG::NodesIterator> ni = rifg->getNodesIterator();
00267 for ( ; (ni->isValid()); ++(*ni)) {
00268 gId = ni->current();
00269 int gdfn = dfnum(gId);
00270
00271 if (gdfn != DFNUM_NIL) {
00272 TARJ_inners(gdfn) = DFNUM_NIL;
00273 TARJ_next(gdfn) = DFNUM_NIL;
00274 }
00275 }
00276
00277
00278
00279 std::list<RIFG::NodeId>::iterator i;
00280 for (i = rev_top_list.begin(); i != rev_top_list.end(); i++) {
00281 gId = *i;
00282 if (gId != RIFG::NIL) {
00283
00284 int gdfn = dfnum(gId);
00285 parent = TARJ_outer(gdfn);
00286 if (parent != DFNUM_NIL) {
00287 TARJ_next(gdfn) = TARJ_inners(parent);
00288 TARJ_inners(parent) = gdfn;
00289 }
00290 }
00291 }
00292
00293 Renumber();
00294 }
00295
00296
00297 TarjTreeNode*
00298 NestedSCR::getTree()
00299 {
00300 return tarj;
00301 }
00302
00303
00304
00305
00306
00307
00308 void
00309 NestedSCR::Init()
00310 {
00311 unsigned int g_size = rifg->getHighWaterMarkNodeId() + 1;
00312
00313 n = DFNUM_ROOT;
00314
00315
00316
00317
00318 wk = new TarjWork[g_size];
00319 uf = new UnionFindUniverse(g_size);
00320 tarj = new TarjTreeNode[g_size];
00321 InitArrays();
00322 }
00323
00324
00325
00326
00327
00328 void
00329 NestedSCR::InitArrays()
00330 {
00331 OA_ptr<RIFG::NodesIterator> ni = rifg->getNodesIterator();
00332 for ( ; ni->isValid(); ++(*ni)) {
00333 int nid = ni->current();
00334 dfnum(nid) = DFNUM_NIL;
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343 void
00344 NestedSCR::DFS(RIFG::NodeId v)
00345 {
00346 vertex(n) = v;
00347 dfnum(v) = n++;
00348
00349 RIFG::EdgeId succ;
00350 OA_ptr<RIFG::OutgoingEdgesIterator> ei = rifg->getOutgoingEdgesIterator(v);
00351 for (; (ei->isValid()); ++(*ei)) {
00352 succ = ei->current();
00353 int son = rifg->getEdgeSink(succ);
00354 if (dfnum(son) == DFNUM_NIL)
00355 DFS(son);
00356 }
00357
00358
00359
00360
00361 TLast(dfnum(v)) = n-1;
00362 rev_top_list.push_back(v);
00363 }
00364
00365
00366
00367 void
00368 NestedSCR::FillPredLists()
00369 {
00370 for (int i = DFNUM_ROOT; i < n; i++) {
00371 OA_ptr<RIFG::IncomingEdgesIterator> ei =
00372 rifg->getIncomingEdgesIterator(vertex(i) );
00373 for ( ; (ei->isValid()); ++(*ei)) {
00374 int prednum = dfnum(rifg->getEdgeSrc(ei->current()));
00375 if (is_backedge(prednum, i)) {
00376 backPreds(i).push_back(prednum);
00377 } else {
00378 nonBackPreds(i).push_back(prednum);
00379 }
00380 }
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 void
00391 NestedSCR::GetTarjans()
00392 {
00393 int w;
00394 DFNUM_t firstP, firstQ;
00395
00396
00397
00398
00399 for (w = n - 1; w != DFNUM_ROOT; w--)
00400
00401
00402
00403 if (w != DFNUM_NIL && rifg->isValid(vertex(w))) {
00404 firstP = firstQ = DFNUM_NIL;
00405
00406
00407
00408 std::list<int>::iterator prednum;
00409 for (prednum = backPreds(w).begin(); prednum != backPreds(w).end();
00410 prednum++) {
00411 int u,v;
00412 v = *prednum;
00413
00414 if (v != DFNUM_NIL)
00415 {
00416 if (v == w) {
00417
00418
00419
00420 isCyclic(w) = true;
00421 } else {
00422
00423
00424
00425 u = FIND(v);
00426 if (!inP(u)) {
00427 nextP(u) = nextQ(u) = firstP;
00428 firstP = firstQ = u;
00429 inP(u) = true;
00430 }
00431 }
00432 }
00433 }
00434
00435
00436
00437
00438 if (firstP != DFNUM_NIL)
00439 isCyclic(w) = true;
00440
00441 while (firstQ != DFNUM_NIL) {
00442 int x, y, yy;
00443
00444 x = firstQ;
00445 firstQ = nextQ(x);
00446
00447
00448
00449
00450 std::list<int>::iterator prednum;
00451 for (prednum = nonBackPreds(x).begin();
00452 prednum != nonBackPreds(x).end();
00453 prednum++) {
00454 y = *prednum;
00455
00456
00457
00458
00459 if (y != DFNUM_NIL)
00460 {
00461
00462
00463
00464 yy = FIND(y);
00465
00466 if (is_backedge(yy, w)) {
00467 if ((!inP(yy)) & (yy != w)) {
00468 nextP(yy) = firstP;
00469 nextQ(yy) = firstQ;
00470 firstP = firstQ = yy;
00471 inP(yy) = true;
00472 }
00473
00474
00475
00476
00477
00478 } else {
00479
00480
00481
00482 reducible(w) = false;
00483 #if 1
00484
00485
00486
00487 nonBackPreds(w).push_back(yy);
00488 #endif
00489 }
00490 }
00491 }
00492 }
00493
00494
00495
00496 while (firstP != DFNUM_NIL) {
00497
00498
00499
00500
00501
00502 if ((header(firstP) == DFNUM_ROOT) & (firstP != w))
00503 header(firstP) = w;
00504 UNION(firstP, w, w);
00505 inP(firstP) = false;
00506 firstP = nextP(firstP);
00507 }
00508 }
00509 }
00510
00511
00512
00513
00514
00515 void
00516 NestedSCR::Build()
00517 {
00518 int w;
00519 int outer;
00520
00521 TARJ_nodeid(DFNUM_ROOT) = rifg->getSource();
00522
00523
00524
00525
00526 for (w = DFNUM_ROOT + 1; w < n; w++) {
00527 RIFG::NodeId wnode = vertex(w);
00528
00529
00530
00531 if (wnode != RIFG::NIL) {
00532 outer = header(w);
00533 TARJ_outer(w) = outer;
00534 TARJ_nodeid(w) = wnode;
00535
00536
00537
00538 if (isCyclic(w)) {
00539
00540
00541
00542 if (reducible(w)) {
00543 TARJ_type(w) = NODE_INTERVAL;
00544 TARJ_level(w) = TARJ_level(outer) + 1;
00545 } else {
00546 TARJ_type(w) = NODE_IRREDUCIBLE;
00547 TARJ_level(w) = TARJ_level(outer);
00548 }
00549 } else {
00550
00551
00552
00553 TARJ_level(w) = TARJ_level(outer);
00554 }
00555 TARJ_next(w) = TARJ_inners(outer);
00556 TARJ_inners(outer) = w;
00557 }
00558 }
00559 n = 0;
00560 Prenumber(DFNUM_ROOT);
00561 }
00562
00563
00564 void
00565 NestedSCR::Prenumber(int v)
00566 {
00567 int inner;
00568
00569 tarj[v].prenum = ++n;
00570 last_id = TARJ_nodeid(v);
00571
00572 for (inner = TARJ_inners(v); inner != DFNUM_NIL;
00573 inner = TARJ_next(inner)) {
00574 Prenumber(inner);
00575 }
00576
00577
00578 tarj[v].last_id = last_id;
00579 tarj[v].last = dfnum(last_id);
00580 }
00581
00582
00583 void
00584 NestedSCR::Renumber()
00585 {
00586 tarj = tarj;
00587 n = 0;
00588 Prenumber(DFNUM_ROOT);
00589 }
00590
00591
00592
00593
00594 void
00595 NestedSCR::FreeWork()
00596 {
00597 delete[] wk;
00598 wk = 0;
00599
00600 delete uf;
00601 uf = 0;
00602 }
00603
00604
00605 static int loopIndex;
00606 void
00607 NestedSCR::ComputeIntervalIndexSubTree(int node, int value)
00608 {
00609 int kid, valKid;
00610
00611 TARJ_loopIndex(node) = value;
00612 if (TARJ_inners(node) != DFNUM_NIL)
00613 valKid = ++loopIndex;
00614
00615 for (kid = TARJ_inners(node); kid != DFNUM_NIL; kid = TARJ_next(kid))
00616 ComputeIntervalIndexSubTree(kid, valKid);
00617 }
00618
00619
00620 void
00621 NestedSCR::ComputeIntervalIndex()
00622 {
00623 loopIndex = 0;
00624 ComputeIntervalIndexSubTree(DFNUM_ROOT, loopIndex);
00625 }
00626
00627
00628 void
00629 NestedSCR::dump(std::ostream& os)
00630 {
00631 printf("Tarjan interval tree: <node id>(level,type)::IntervalIndex\n");
00632 DumpSubTree(os, DFNUM_ROOT, 0 );
00633 }
00634
00635
00636
00637
00638
00639
00640 void
00641 NestedSCR::DumpSubTree(std::ostream& os, int node, int indent)
00642 {
00643 static const char *NodeType[] = {"NOTHING", "Acyclic",
00644 "Interval", "Irreducible"};
00645
00646
00647
00648 if (indent < 72)
00649 indent += 3;
00650
00651 printf("%*s%d(%d,%s)::%d\n", indent, " ",
00652 TARJ_nodeid(node), TARJ_level(node),
00653 NodeType[(int) (TARJ_type(node))], TARJ_loopIndex(node));
00654
00655 for (int kid = TARJ_inners(node); kid != DFNUM_NIL;
00656 kid = TARJ_next(kid)) {
00657 DumpSubTree(os, kid, indent);
00658 }
00659
00660
00661
00662
00663 if (indent >= 3)
00664 indent -= 3;
00665 }
00666
00667
00668 int
00669 NestedSCR::FIND(int v)
00670 {
00671 return uf->Find(v);
00672 }
00673
00674
00675 void
00676 NestedSCR::UNION(int i, int j, int k)
00677 {
00678 uf->Union(i,j,k);
00679 }
00680
00681
00682
00683
00684
00685
00686 int
00687 NestedSCR::getExits(RIFG::NodeId src, RIFG::NodeId sink)
00688 {
00689 RIFG::NodeId lca = LCA(src, sink);
00690 if (lca == RIFG::NIL)
00691 return 0;
00692
00693 int dfn_src = dfnum(src);
00694 int dfn_lca = dfnum(lca);
00695 return std::max(0, TARJ_level(dfn_src) - TARJ_level(dfn_lca));
00696 }
00697
00698
00699
00700
00701
00702
00703 RIFG::NodeId
00704 NestedSCR::getLoopExited(RIFG::NodeId src, RIFG::NodeId sink)
00705 {
00706 RIFG::NodeId lca = LCA(src, sink);
00707 if (lca == RIFG::NIL)
00708 return RIFG::NIL;
00709
00710 if (lca == src)
00711 return RIFG::NIL;
00712
00713 int dfn_src = dfnum(src);
00714 while (!Contains(TARJ_nodeid(TARJ_outer(dfn_src)), sink))
00715 dfn_src = TARJ_outer(dfn_src);
00716
00717 if (TARJ_type(dfn_src) == NODE_INTERVAL
00718 || TARJ_type(dfn_src) == NODE_IRREDUCIBLE)
00719 return TARJ_nodeid(dfn_src);
00720
00721 return RIFG::NIL;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 NestedSCR::Edge_t
00733 NestedSCR::getEdgeType(RIFG::NodeId src, RIFG::NodeId sink)
00734 {
00735 RIFG::NodeId anc = LCA(src, sink);
00736 int dfn_sink = dfnum(sink);
00737 int dfn_anc = dfnum(anc);
00738
00739 if (dfn_anc == dfn_sink) {
00740 return EDGE_ITERATE;
00741 }
00742 else if (TARJ_outer(dfn_sink) != DFNUM_NIL
00743 && (TARJ_type(TARJ_outer(dfn_sink)) == NODE_IRREDUCIBLE)
00744 && (dfn_anc != TARJ_outer(dfn_sink))) {
00745
00746
00747
00748 return EDGE_IRRED_ENTRY;
00749 }
00750 else {
00751 switch (TARJ_type(dfn_sink)) {
00752 case NODE_INTERVAL:
00753 return EDGE_LOOP_ENTRY;
00754 case NODE_IRREDUCIBLE:
00755
00756
00757
00758 return EDGE_IRRED_ENTRY;
00759 case NODE_ACYCLIC:
00760 case NODE_NOTHING:
00761 default:
00762 return EDGE_NORMAL;
00763 }
00764 }
00765 }
00766
00767
00768
00769
00770
00771 RIFG::NodeId
00772 NestedSCR::LCA(RIFG::NodeId a, RIFG::NodeId b)
00773 {
00774 if ((a == RIFG::NIL) || (b == RIFG::NIL))
00775 return RIFG::NIL;
00776
00777 if (Contains(a,b))
00778 return a;
00779
00780 int dfn_b = dfnum(b);
00781 while ((dfn_b != DFNUM_NIL) && !Contains(b,a)) {
00782 dfn_b = TARJ_outer(dfn_b);
00783 b = TARJ_nodeid(dfn_b);
00784 }
00785
00786 return b;
00787 }
00788
00789
00790
00791
00792
00793
00794
00795 bool
00796 NestedSCR::isBackEdge(RIFG::EdgeId edgeId)
00797 {
00798 RIFG::NodeId src, dest;
00799 src = rifg->getEdgeSrc(edgeId);
00800 dest = rifg->getEdgeSink(edgeId);
00801 return is_backedge(dfnum(src), dfnum(dest));
00802 }
00803
00804
00805 RIFG::NodeId
00806 NestedSCR::getInners(RIFG::NodeId id)
00807 {
00808 int dfn_inners = TARJ_inners(dfnum(id));
00809 return dfn_inners == DFNUM_NIL ? RIFG::NIL : TARJ_nodeid(dfn_inners);
00810 }
00811
00812
00813 RIFG::NodeId
00814 NestedSCR::getInnersLast(RIFG::NodeId id)
00815 {
00816 int dfn_last_id = TARJ_last_id(dfnum(id));
00817 return TARJ_nodeid(dfn_last_id);
00818 }
00819
00820
00821 RIFG::NodeId
00822 NestedSCR::getOuter(RIFG::NodeId id)
00823 {
00824 int dfn_outer = TARJ_outer(dfnum(id));
00825 return dfn_outer == DFNUM_NIL ? RIFG::NIL : TARJ_nodeid(dfn_outer);
00826 }
00827
00828
00829 RIFG::NodeId
00830 NestedSCR::getNext(RIFG::NodeId id)
00831 {
00832 int dfn_next = TARJ_next(dfnum(id));
00833 return dfn_next == DFNUM_NIL ? RIFG::NIL : TARJ_nodeid(dfn_next);
00834 }
00835
00836
00837
00838 bool
00839 NestedSCR::isHeader(RIFG::NodeId id)
00840 {
00841 return (getInners(dfnum(id)) != DFNUM_NIL);
00842 }
00843
00844
00845 bool
00846 NestedSCR::isFirst(RIFG::NodeId id)
00847 {
00848 int dfn_id = dfnum(id);
00849
00850 if (getOuter(dfn_id) == DFNUM_NIL)
00851 return true;
00852
00853 return (getInners(getOuter(dfn_id)) == dfn_id);
00854 }
00855
00856
00857 bool
00858 NestedSCR::isLast(RIFG::NodeId id)
00859 {
00860 return (getNext(dfnum(id)) == DFNUM_NIL);
00861 }
00862
00863
00864 int
00865 NestedSCR::getLevel(RIFG::NodeId id)
00866 {
00867 return TARJ_level(dfnum(id));
00868 }
00869
00870
00871 NestedSCR::Node_t
00872 NestedSCR::getNodeType(RIFG::NodeId id)
00873 {
00874 return TARJ_type(dfnum(id));
00875 }
00876
00877
00878 bool
00879 NestedSCR::Contains(RIFG::NodeId a, RIFG::NodeId b)
00880 {
00881 return (TARJ_contains(dfnum(a), dfnum(b)));
00882 }
00883
00884
00885 int
00886 NestedSCR::getLoopIndex(RIFG::NodeId id)
00887 {
00888 return TARJ_loopIndex(dfnum(id));
00889 }
00890
00891
00892 }
00893