/*!\func * calc size * \params no * \return no */ void EdgeAssotiation::adjust() { if (!sourceNode() || !destNode()) return; prepareGeometryChange(); sourcePoint = sourceNode()->pos() + QPointF(sourceNode()->boundingRect().width()/2, sourceNode()->boundingRect().height()/2); destPoint = destNode()->pos() + QPointF(destNode()->boundingRect().width()/2, destNode()->boundingRect().height()/2); middlePoint = QPointF(destPoint.x(),sourcePoint.y()); }
/*! \func * figure * \param no * \return no */ QPainterPath Edge::shape() const { QPainterPath path; path.moveTo(destNode()->pos() + QPointF(2,2)); path.lineTo(sourceNode()->pos() + QPointF(2,2)); path.lineTo(sourceNode()->pos() + QPointF(-2,-2)); path.lineTo(destNode()->pos() + QPointF(-2,-2)); return path; }
GraphicEdge::~GraphicEdge() { MainWindow* mw = dynamic_cast<MainWindow*>(graph->parent()); mw->net->remove_edge(net_edge); sourceNode()->removeEdge(this); destNode()->removeEdge(this); }
/*!\func * draw edge * \params no * \return no */ void EdgeAssotiation::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { if (!sourceNode() || !destNode()) return; QColor color (Qt::black); switch (getState()) { case OFF: color = Qt::gray; break; case OK: color = Qt::green; break; case WARNING: default: color = Qt::red; } painter->setPen(QPen(color, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); float width = destNode()->boundingRect().width(); float height = destNode()->boundingRect().height(); QRectF rect(destNode()->pos().x() , destNode()->pos().y(), width, height); width = sourceNode()->boundingRect().width(); height = sourceNode()->boundingRect().height(); QRectF rects(sourceNode()->pos().x(), sourceNode()->pos().y(), width, height); painter->setBrush(color); painter->drawLine(destPoint, middlePoint); painter->drawLine(middlePoint, sourcePoint); painter->setPen(Qt::SolidLine); if(rect.contains(middlePoint)) {//arrow enter in node by left or right int sign = destPoint.x() > sourcePoint.x() ? 1 : -1; //QMessageBox::information(0,"","arrow enter in node by left or right"); QPointF destArrowP1 = QPointF(middlePoint.x() - sign*rect.width()/2, middlePoint.y()); QPointF destArrowP2 = QPointF(middlePoint.x() - sign*(rect.width()/2 + arrowSize), middlePoint.y()-arrowSize/2); QPointF destArrowP3 = QPointF(middlePoint.x() - sign*(rect.width()/2 + arrowSize), middlePoint.y()+arrowSize/2); painter->setBrush(color); painter->drawPolygon(QPolygonF() << destArrowP3 << destArrowP1 << destArrowP2); } else {//arrow enter in node by top or bottom int sign = destPoint.y() > sourcePoint.y() ? 1 : -1; //QMessageBox::information(0,"","arrow enter in node by left or right"); QPointF destArrowP1 = QPointF(destPoint.x(), destPoint.y()-sign*rect.height()/2); QPointF destArrowP2 = QPointF(destPoint.x()-arrowSize/2, destPoint.y() - sign*(rect.height()/2 + arrowSize)); QPointF destArrowP3 = QPointF(destPoint.x()+arrowSize/2, destPoint.y() - sign*(rect.height()/2 + arrowSize)); painter->setBrush(color); painter->drawPolygon(QPolygonF() << destArrowP3 << destArrowP1 << destArrowP2); } if(rects.contains(middlePoint)) name->setPos((sourcePoint + destPoint)/2); else { if(sourcePoint.x() < destPoint.x()) name->setPos(sourcePoint + QPointF(sourceNode()->boundingRect().width()/2,-name->boundingRect().height())); else name->setPos(sourcePoint + QPointF(-name->boundingRect().width()-sourceNode()->boundingRect().width()/2,-name->boundingRect().height())); } }
void Edge2d::adjust() { if (!source || !dest) return; QLineF line(mapFromItem(source, sourceNode()->getRadius(), sourceNode()->getRadius()), mapFromItem(dest, destNode()->getRadius(), destNode()->getRadius())); //line centre source à centre dest qreal length = line.length(); prepareGeometryChange(); //cas ou les 2 nodes se chevauchent, on n'afficher pas l'edge if (length > qreal(sourceNode()->getRadius() + destNode()->getRadius())) { // QPointF edgeOffsetSource((line.dx() * sqrt(2) * sourceNode()->getRadius()*2) / length, (line.dy() * 12) / length); //QPointF edgeOffsetDest((line.dx() * 25) / length, (line.dy() * 25) / length); sourcePoint = line.p1();// + edgeOffsetSource; destPoint = line.p2();// - edgeOffsetDest; } else { sourcePoint = destPoint = line.p1(); } }
/*! \func * rect * \params no * \return no */ QRectF EdgeAssotiation::boundingRect() const { if (!sourceNode() || !destNode()) return QRectF(); if(sourcePoint == destPoint) { return QRectF(destPoint.x() - 28, destPoint.y() - 28, 30, 30); } QPointF leftTop(qMin(sourcePoint.x(), destPoint.x())-arrowSize, qMin(sourcePoint.y(), destPoint.y())-arrowSize); QSizeF size(abs(sourcePoint.x() - destPoint.x())+2*arrowSize, abs(sourcePoint.y() - destPoint.y())+2*arrowSize); return QRectF(leftTop, size); }
/*! \func * draw all * \param * - painter - painter device * \return no */ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { static const double Pi = 3.14159265358979323846264338327950288419717; static double TwoPi = 2.0 * Pi; if (!source || !dest) return; QColor color (Qt::black); switch (state) { case OFF: color = Qt::gray; break; case OK: color = Qt::green; break; case WARNING: default: color = Qt::red; } // Draw the line itself if(sourceNode()->getId() == destNode()->getId()) { painter->setPen(QPen(color, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->drawEllipse(destPoint.x() - 28, destPoint.y() - 28, 30, 30); painter->setPen(Qt::black); //painter->drawText(destPoint+QPoint(-28,-14), name); } else { QLineF line(sourcePoint, destPoint); painter->setPen(QPen(color, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->drawLine(line); // Draw the arrows if there's enough room double angle = ::acos(line.dx() / line.length()); if (line.dy() >= 0) angle = TwoPi - angle; QPointF destArrowP1 = destPoint + QPointF(sin(angle - Pi / 3) * arrowSize, cos(angle - Pi / 3) * arrowSize); QPointF destArrowP2 = destPoint + QPointF(sin(angle - Pi + Pi / 3) * arrowSize, cos(angle - Pi + Pi / 3) * arrowSize); QPointF destArrowP3 = destPoint + QPointF(sin(angle + Pi / 2) * arrowSize, cos(angle + Pi / 2) * arrowSize); painter->setBrush(color); painter->drawPolygon(QPolygonF() << destArrowP3 << destArrowP1 << destArrowP2); painter->setPen(Qt::black); //painter->drawText((destPoint + sourcePoint)/2, name); name->setPos((destPoint + sourcePoint)/2); } }
static Arc best_predecessor_1 (Node node) { Node src, dest; Arc ln, best; dest = node; /* * Find a source node with the largest weight. */ src = 0; best = 0; for (ln = sourceArcs (dest); ln != 0; ln = nextArc (ln)) { Node new_node; new_node = sourceNode (ln); if (src == 0) { src = new_node; best = ln; } else { if (predecessor_node_weight (new_node, dest) > predecessor_node_weight (src, dest)) { src = new_node; best = ln; } } } /* * The selected node must be unvisited, and * has non-zero weight. */ if ((src == 0) || (nodeStatus (src) & VISITED)) return 0; if (nodeWeight (src) == 0.0) return 0; /* * Return the best link. */ return best; }
static double predecessor_arc_weight (Arc arc) { struct Ext *extSRC, *extDEST; int diff; double weight; extSRC = (struct Ext *) nodeExt (sourceNode (arc)); extDEST = (struct Ext *) nodeExt (destinationNode (arc)); diff = extDEST->level - extSRC->level; if (diff > 0) { weight = arcWeight (arc) + (diff * SCALE); } else { weight = arcWeight (arc); } return weight; }
static Arc best_predecessor_3 (Node node) { Node src, dest; Arc ln, best; dest = node; /* * Find an incoming arc with the highest execution count. */ best = 0; for (ln = sourceArcs (dest); ln != 0; ln = nextArc (ln)) { if (best == 0) { best = ln; } else { if (predecessor_arc_weight (ln) > predecessor_arc_weight (best)) best = ln; } } /* * The best link must have non-zero weight. */ if ((best == 0) || (arcWeight (best) == 0.0)) return 0; src = sourceNode (best); /* * The source node must be un-visited. */ if (nodeStatus (src) & VISITED) return 0; if ((arcWeight (best) / nodeWeight (src)) < min_prob_requirement) return 0; if ((arcWeight (best) / nodeWeight (dest)) < min_prob_requirement) return 0; /* * Return the best link. */ return best; }
static double successor_arc_weight (Arc arc) { struct Ext *extSRC, *extDEST; int diff; double weight; extSRC = (struct Ext *) nodeExt (sourceNode (arc)); extDEST = (struct Ext *) nodeExt (destinationNode (arc)); diff = extDEST->level - extSRC->level; /* * when choosing a successor, select one * that is closer to it (level information) * when the dynamic count is low. */ if (diff > 0) { weight = arcWeight (arc) + ((FAVOR_FORWARD - diff) * SCALE); } else { weight = arcWeight (arc); } return weight; }
/* * Measure the trace selection result. * Trace selection must have been applied. */ void ReportSelectionResult (FGraph graph, double *matrix) { int i; Node node; Arc arc; if (graph == 0) Punt ("ReportSelectionResult: nil graph"); if (matrix == 0) return; for (i = 0; i <= N_LEAF; i++) matrix[i] = 0.0; /* * Compute the sequential locality. */ for (node = graph->nodes; node != 0; node = nextNode (node)) { Arc ptr; Node next_node; next_node = nextNode (node); if (next_node == 0) /* ignore the last node */ break; for (ptr = destinationArcs (node); ptr != 0; ptr = nextArc (ptr)) { if (destinationNode (ptr) == next_node) { matrix[W_SEQUENTIAL] += arcWeight (ptr); } } } /* * Measure various transition counts. */ for (node = graph->nodes; node != 0; node = nextNode (node)) { for (arc = destinationArcs (node); arc != 0; arc = nextArc (arc)) { Node src, dest; int Sh, St, Dh, Dt; src = sourceNode (arc); dest = destinationNode (arc); Sh = nodeStatus (src) & TRACE_HEAD; St = nodeStatus (src) & TRACE_TAIL; Dh = nodeStatus (dest) & TRACE_HEAD; Dt = nodeStatus (dest) & TRACE_TAIL; if ((arcType (arc) != 0) && (arcType (arc) == nodeType (node))) { /* * In-trace. */ matrix[W_E] += arcWeight (arc); } else if (arcType (arc) != 0) { Punt ("ReportSelectionResult: illegal arc type"); } else { if (St && Dh) { /* terminal to head */ matrix[W_A] += arcWeight (arc); /* detect loop back-edge */ if (nodeType (src) == nodeType (dest)) { matrix[W_BACK_EDGE] += arcWeight (arc); } } else if (St && !Dh) { /* terminal to middle */ matrix[W_B] += arcWeight (arc); } else if (!St && Dh) { /* middle to head */ matrix[W_C] += arcWeight (arc); } else { /* middle to middle */ matrix[W_D] += arcWeight (arc); } } } } #ifdef DEBUG_TRACE2 if (matrix[W_E] > matrix[W_SEQUENTIAL]) { WriteGraph ("zzz.debug", graph); fprintf (stderr, "in-trace = %f\n", matrix[W_E]); fprintf (stderr, "sequential = %f\n", matrix[W_SEQUENTIAL]); Punt ("ReportSelection: incorrect in-trace"); } #endif /* * Measure several graph parameters. */ for (node = graph->nodes; node != 0; node = nextNode (node)) { nodeStatus (node) &= ~VISITED; /* borrow the valid bit */ matrix[N_NODES] += 1.0; matrix[W_NODES] += nodeWeight (node); if (destinationArcs (node) == 0) { matrix[N_LEAF] += 1.0; } if (sourceArcs (node) == 0) { matrix[N_ROOT] += 1.0; } for (arc = destinationArcs (node); arc != 0; arc = nextArc (arc)) { matrix[N_ARCS] += 1.0; matrix[W_ARCS] += arcWeight (arc); } } for (node = graph->nodes; node != 0; node = nextNode (node)) { Node ptr; int trace_id, loop, size; if (nodeStatus (node) & VISITED) continue; trace_id = nodeType (node); loop = 0; size = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (nodeType (ptr) == trace_id) { nodeStatus (ptr) |= VISITED; size++; loop |= (nodeStatus (node) & LOOP_HEAD); } } matrix[N_TRACE] += 1.0; matrix[L_TRACE] += size; if (loop) { matrix[N_LOOP] += 1.0; matrix[L_LOOP] += size; } } if (matrix[L_TRACE] != matrix[N_NODES]) Punt ("ReportSelectionResult: incorrect accounting"); if (matrix[N_TRACE] != 0.0) matrix[L_TRACE] /= matrix[N_TRACE]; if (matrix[N_LOOP] != 0.0) matrix[L_LOOP] /= matrix[N_LOOP]; }
static void AddExtensionFields (FGraph graph) { Node ptr; Arc arc; struct Ext *ext; int change; Set all; FreeExtensionFields (); if (graph->nodes == 0) return; if (graph->root == 0) Punt ("no root node"); all = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { nodeExt (ptr) = (others + n_others); others[n_others].dominator = 0; others[n_others].level = -1; others[n_others].order = n_others; all = Set_add (all, n_others); n_others += 1; } ext = (struct Ext *) nodeExt (graph->root); ext->level = 0; ext->dominator = Set_add (0, ext->order); for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (ptr == graph->root) continue; ext = (struct Ext *) nodeExt (ptr); ext->dominator = Set_union (0, all); } /* * compute dominators. */ change = 1; while (change != 0) { change = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { Set dom, temp; if (ptr == graph->root) continue; arc = sourceArcs (ptr); if (arc == 0) { dom = 0; } else { dom = Set_union (all, 0); for (; arc != 0; arc = nextArc (arc)) { ext = (struct Ext *) nodeExt (sourceNode (arc)); temp = Set_intersect (dom, ext->dominator); Set_dispose (dom); dom = temp; temp = 0; } ext = (struct Ext *) nodeExt (ptr); dom = Set_add (dom, ext->order); if (Set_same (dom, ext->dominator)) { Set_dispose (dom); } else { Set_dispose (ext->dominator); ext->dominator = dom; change += 1; } } } } all = Set_dispose (all); /* * compute level. */ change = 1; while (change != 0) { change = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { int max; ext = (struct Ext *) nodeExt (ptr); if (ext->level >= 0) continue; max = -1; for (arc = sourceArcs (ptr); arc != 0; arc = arc->next) { Node src; struct Ext *ex; src = sourceNode (arc); ex = (struct Ext *) nodeExt (src); /* ignore back-edges */ if (ex->order >= ext->order) continue; if (ex->level < 0) break; if (ex->level > max) max = ex->level; } if (arc == 0) { /* all source have been visited */ ext->level = max + 1; change += 1; } } } #ifdef DEBUG printf ("--------------------------------------------------\n"); for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { ext = nodeExt (ptr); printf ("# id=%d, order=%d, level=%d, ", ptr->id, ext->order, ext->level); PrintSet (stdout, "dominator", ext->dominator); } #endif }
//! remove void Edge::Remove() { hide(); sourceNode()->delEdge(this); destNode()->delEdge(this); }
bool PxrUsdTranslators_InstancerWriter::writeInstancerAttrs( const UsdTimeCode& usdTime, const UsdGeomPointInstancer& instancer) { MStatus status = MS::kSuccess; MFnDagNode dagNode(GetDagPath(), &status); CHECK_MSTATUS_AND_RETURN(status, false); // Note: In this function, we don't read instances using the provided // MFnInstancer API. One reason is that it breaks up prototypes into their // constituent shapes, and there's no way to figure out which hierarchy // they came from. Another reason is that it only provides computed matrices // and not separate position, rotation, scale attrs. const SdfPath prototypesGroupPath = instancer.GetPrim().GetPath().AppendChild(_tokens->Prototypes); // At the default time, setup all the prototype instances. if (usdTime.IsDefault()) { const MPlug inputHierarchy = dagNode.findPlug("inputHierarchy", true, &status); CHECK_MSTATUS_AND_RETURN(status, false); // Note that the "Prototypes" prim needs to be a model group to ensure // contiguous model hierarchy. const UsdPrim prototypesGroupPrim = GetUsdStage()->DefinePrim( prototypesGroupPath); UsdModelAPI(prototypesGroupPrim).SetKind(KindTokens->group); _modelPaths.push_back(prototypesGroupPath); UsdRelationship prototypesRel = instancer.CreatePrototypesRel(); const unsigned int numElements = inputHierarchy.numElements(); for (unsigned int i = 0; i < numElements; ++i) { const MPlug plug = inputHierarchy[i]; const MPlug source(UsdMayaUtil::GetConnected(plug)); if (source.isNull()) { TF_WARN("Cannot read prototype: the source plug %s was null", plug.name().asChar()); return false; } MFnDagNode sourceNode(source.node(), &status); CHECK_MSTATUS_AND_RETURN(status, false); MDagPath prototypeDagPath; sourceNode.getPath(prototypeDagPath); // Prototype names are guaranteed unique by virtue of having a // unique numerical suffix _# indicating the prototype index. const TfToken prototypeName( TfStringPrintf("%s_%d", sourceNode.name().asChar(), i)); const SdfPath prototypeUsdPath = prototypesGroupPrim.GetPath() .AppendChild(prototypeName); UsdPrim prototypePrim = GetUsdStage()->DefinePrim( prototypeUsdPath); _modelPaths.push_back(prototypeUsdPath); // Try to be conservative and only create an intermediary xformOp // with the instancerTranslate if we can ensure that we don't need // to compensate for the translation on the prototype root. // // XXX: instancerTranslate does not behave well when added to a // reference that has an existing transform on the far side of the // reference. However, its behavior at least matches the // behavior in UsdMayaTranslatorModelAssembly. If we fix the // behavior there, we need to make sure that this is also // fixed to match. bool instancerTranslateAnimated = false; if (_NeedsExtraInstancerTranslate( prototypeDagPath, &instancerTranslateAnimated)) { UsdGeomXformable xformable(prototypePrim); UsdGeomXformOp newOp = xformable.AddTranslateOp( UsdGeomXformOp::PrecisionDouble, _tokens->instancerTranslate); _instancerTranslateOps.push_back( {prototypeDagPath, newOp, instancerTranslateAnimated}); } // Two notes: // (1) We don't un-instance here, because it's OK for the prototype // to just be a reference to an instance master if the prototype // participates in Maya native instancing. // (2) The prototype root must be visible to match Maya's behavior, // which always vis'es the prototype root, even if it is marked // hidden. _writeJobCtx.CreatePrimWriterHierarchy( prototypeDagPath, prototypeUsdPath, /*forceUninstance*/ false, /*exportRootVisibility*/ false, &_prototypeWriters); prototypesRel.AddTarget(prototypeUsdPath); } _numPrototypes = numElements; } // If there aren't any prototypes, fail and don't export on subsequent // time-sampled exports. if (_numPrototypes == 0) { return false; } // Actual write of prototypes (@ both default time and animated time). for (UsdMayaPrimWriterSharedPtr& writer : _prototypeWriters) { writer->Write(usdTime); if (usdTime.IsDefault()) { // Prototype roots should have kind component or derived. // Calling Write() above may have populated kinds, so don't stomp // over existing component-derived kinds. // (Note that ModelKindWriter's fix-up stage might change this.) if (writer->GetUsdPath().GetParentPath() == prototypesGroupPath) { if (const UsdPrim writerPrim = writer->GetUsdPrim()) { UsdModelAPI primModelAPI(writerPrim); TfToken kind; primModelAPI.GetKind(&kind); if (!KindRegistry::IsA(kind, KindTokens->component)) { primModelAPI.SetKind(KindTokens->component); } } } } } // Write the instancerTranslate xformOp for all prims that need it. // (This should happen @ default time or animated time depending on whether // the xform is animated.) for (const _TranslateOpData& opData : _instancerTranslateOps) { if (opData.isAnimated != usdTime.IsDefault()) { GfVec3d origin; if (_GetTransformedOriginInLocalSpace(opData.mayaPath, &origin)) { UsdGeomXformOp translateOp = opData.op; _SetAttribute(translateOp.GetAttr(), -origin, usdTime); } } } // Grab the inputPoints data from the source plug. // (This attribute's value must come from a source plug; it isn't // directly writeable. Thus reading it directly may not give the right // value depending on Maya's execution behavior.) MPlug inputPointsDest = dagNode.findPlug("inputPoints", true, &status); CHECK_MSTATUS_AND_RETURN(status, false); MPlug inputPointsSrc = UsdMayaUtil::GetConnected(inputPointsDest); if (inputPointsSrc.isNull()) { TF_WARN("inputPoints not connected on instancer '%s'", GetDagPath().fullPathName().asChar()); return false; } auto holder = UsdMayaUtil::GetPlugDataHandle(inputPointsSrc); if (!holder) { TF_WARN("Unable to read inputPoints data handle for instancer '%s'", GetDagPath().fullPathName().asChar()); return false; } MFnArrayAttrsData inputPointsData(holder->GetDataHandle().data(), &status); CHECK_MSTATUS_AND_RETURN(status, false); if (!UsdMayaWriteUtil::WriteArrayAttrsToInstancer( inputPointsData, instancer, _numPrototypes, usdTime, _GetSparseValueWriter())) { return false; } // Load the completed point instancer to compute and set its extent. instancer.GetPrim().GetStage()->Load(instancer.GetPath()); VtArray<GfVec3f> extent(2); if (instancer.ComputeExtentAtTime(&extent, usdTime, usdTime)) { _SetAttribute(instancer.CreateExtentAttr(), &extent, usdTime); } return true; }
/* * Heuristic solution to the trace selection problem. */ static void SelectTraces (FGraph graph) { ST_Entry sorted_list[MAX_GRAPH_SIZE]; int list_length; Node ptr; Arc arc; int n, trace_id; Node ENTRY; Node seed, current, last; struct Ext *extCurrent, *extNext; /* * Compute level information. */ AddExtensionFields (graph); /* * Mark all nodes unvisited. * Also clear all status bits. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { nodeType (ptr) = 0; /* trace id = 0 */ nodeStatus (ptr) = NOT_VISITED; for (arc = sourceArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; } /* * Sort all nodes according to the node weight. * From the most important node to the least important node. */ list_length = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { sorted_list[list_length].weight = nodeWeight (ptr); sorted_list[list_length].ptr = ptr; sorted_list[list_length].index = list_length; list_length += 1; if (list_length >= MAX_GRAPH_SIZE) Punt ("SelectTrace: graph is too large"); } max_sort (sorted_list, list_length); /* library/sort.c */ #ifdef WEIGHT_BASED /* * Give higher priority to the execution weight. */ ENTRY = graph->root; trace_id = 1; for (n = 0; n < list_length; n++) { /* * Select the highest weight un-visited node. */ seed = sorted_list[n].ptr; if (nodeStatus (seed) & VISITED) /* if visited, try next */ continue; /* highest node */ /* * Start a new trace. * Mark seed visited. */ nodeType (seed) = trace_id++; nodeStatus (seed) |= VISITED; /* * Grow the trace forward. */ current = seed; for (;;) { Arc ln, arc; Node dest; ln = best_successor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Cannot include ENTRY node. */ dest = destinationNode (ln); if (dest == ENTRY) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Can not include a dominator. */ extCurrent = nodeExt (current); extNext = nodeExt (dest); if ((extCurrent == 0) | (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extCurrent->dominator, extNext->order)) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Mark the link selected. */ arc = FindSrcArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (dest) = nodeType (seed); nodeStatus (dest) |= VISITED; current = dest; } /* * Grow the trace backward. */ current = seed; for (;;) { Arc ln, arc; Node src; /* * Cannot grow from the ENTRY node. */ if (current == ENTRY) { nodeStatus (current) |= TRACE_HEAD; break; } ln = best_predecessor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_HEAD; break; } src = sourceNode (ln); /* * Can not include a dominee. */ extCurrent = nodeExt (current); extNext = nodeExt (src); if ((extCurrent == 0) | (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extNext->dominator, extCurrent->order)) { nodeStatus (current) |= TRACE_HEAD; break; } /* * Mark the link selected. */ arc = FindSrcArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (src) = nodeType (seed); nodeStatus (src) |= VISITED; current = src; } } #else /* * Give more attention to the natural flow of the * program. */ ENTRY = graph->root; trace_id = 1; current = ENTRY; /* start from the entry block */ last = 0; for (n = 0; n < list_length; n++) { if (!(nodeStatus (current) & VISITED)) { /* * 1) start from the start node first. */ seed = current; } else { /* * 2) select a fall_thru node if possible. * 3) select the most important node. */ Node best, dest; Arc pc; if (last == 0) Punt ("this should not happen"); best = 0; for (pc = destinationArcs (last); pc != 0; pc = nextArc (pc)) { dest = destinationNode (pc); if (nodeStatus (dest) & VISITED) continue; if (best == 0) { best = dest; } else if (successor_node_weight (last, dest) > successor_node_weight (last, best)) { best = dest; } } if (best == 0) { int k; for (k = 0; k < list_length; k++) { dest = (Node) sorted_list[k].ptr; if (nodeStatus (dest) & VISITED) continue; best = dest; break; } } if (best == 0) { break; } seed = best; } if (nodeStatus (seed) & VISITED) Punt ("incorrect seed selection"); /* * Start a new trace. * Mark seed visited. */ nodeType (seed) = trace_id++; nodeStatus (seed) |= VISITED; /* * Grow the trace forward. */ current = seed; for (;;) { Arc ln, arc; Node dest; ln = best_successor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Cannot include ENTRY node. */ dest = destinationNode (ln); if (dest == ENTRY) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Can not include a dominator. */ extCurrent = (struct Ext *) nodeExt (current); extNext = (struct Ext *) nodeExt (dest); if ((extCurrent == 0) || (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extCurrent->dominator, extNext->order)) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Mark the link selected. */ arc = FindSrcArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (dest) = nodeType (seed); nodeStatus (dest) |= VISITED; current = dest; } last = current; /* * Grow the trace backward. */ current = seed; for (;;) { Arc ln, arc; Node src; /* * Cannot grow from the ENTRY node. */ if (current == ENTRY) { nodeStatus (current) |= TRACE_HEAD; break; } ln = best_predecessor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_HEAD; break; } src = sourceNode (ln); /* * Can not include a dominee. */ extCurrent = (struct Ext *) nodeExt (current); extNext = (struct Ext *) nodeExt (src); if ((extCurrent == 0) || (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extNext->dominator, extCurrent->order)) { nodeStatus (current) |= TRACE_HEAD; break; } /* * Mark the link selected. */ arc = FindSrcArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (src) = nodeType (seed); nodeStatus (src) |= VISITED; current = src; } } #endif /* * Make sure that all nodes have been visited. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (!(nodeStatus (ptr) & VISITED)) Punt ("SelectTraces: failed to select all nodes"); } /* * Detect inner loops. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { Arc ln; if (!(nodeStatus (ptr) & TRACE_TAIL)) continue; for (ln = destinationArcs (ptr); ln != 0; ln = nextArc (ln)) { Node dest; dest = destinationNode (ln); if ((nodeStatus (dest) & TRACE_HEAD) && (nodeType (dest) == nodeType (ptr))) { nodeStatus (dest) |= LOOP_HEAD; break; } } } }
/* * Trace selection by sorting all arcs and * select from the most important to the least important. */ void SelectBySortArc (FGraph graph) { #define MAX_SIZE (MAX_GRAPH_SIZE*2) ST_Entry sorted_list[MAX_SIZE]; /* expected fan-out = 2 */ register int list_length; Node node_list[MAX_GRAPH_SIZE]; register int node_list_length; register Node ptr; register Arc arc; register int i; int next_trace_id; /* * Mark all nodes unvisited. * Also clear all status bits. */ node_list_length = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { node_list[node_list_length++] = ptr; if (node_list_length >= MAX_GRAPH_SIZE) Punt ("SelectBySortArc: graph is too large"); nodeType (ptr) = 0; /* trace id = 0 */ nodeStatus (ptr) = NOT_VISITED; for (arc = sourceArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; } /* * Place all outgoing arcs in the list. * Sort all arcs by weight. */ list_length = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) { sorted_list[list_length].weight = arcWeight (arc); sorted_list[list_length].ptr = arc; list_length += 1; if (list_length >= MAX_SIZE) Punt ("SelectBySortArc: graph is too large"); } } max_sort (sorted_list, list_length); /* library/sort.c */ /* * From the most important arc to the least important arc, * connect basic blocks into traces. */ next_trace_id = 1; for (i = 0; i < list_length; i++) { int trace_id; Node src, dest; arc = (Arc) sorted_list[i].ptr; src = sourceNode (arc); dest = destinationNode (arc); /* * Check if this arc can still be selected. * dest cannot be the root of the graph. * case1 : src = free node, dest = free node * case2 : src is a tail node, dest is a head node, * except when src and dest belong to the same trace. */ if (dest == graph->root) continue; if (! ((nodeStatus (src) == NOT_VISITED) || (nodeStatus (src) & TRACE_TAIL))) continue; if (! ((nodeStatus (dest) == NOT_VISITED) || (nodeStatus (dest) & TRACE_HEAD))) continue; /* * If both src and dest are defined (in some trace), * we do not allow this connection if src and dest * belong to the same trace. * This takes care of self-recursions. */ if ((nodeStatus (src) & TRACE_TAIL) && (nodeStatus (dest) & TRACE_HEAD)) if (nodeType (src) == nodeType (dest)) continue; /* * It is also not allow to connect, when src and dest * are the same node. */ if (src == dest) continue; /* * After connection, src will no longer be tail, and * dest will no longer be head. */ nodeStatus (src) &= ~TRACE_TAIL; nodeStatus (dest) &= ~TRACE_HEAD; /* * Now this arc can be selected. */ if (nodeStatus (src) & VISITED) { trace_id = nodeType (src); arcType (arc) = trace_id; /* * If the dest node is in another trace, need to * combine the two traces. */ if (nodeStatus (dest) & VISITED) { register int j; register int bad_id = nodeType (dest); /* * For all nodes of type (nodeType(dest)), change * to trace_id. */ for (j = 0; j < node_list_length; j++) if (nodeType (node_list[j]) == bad_id) nodeType (node_list[j]) = trace_id; /* * For all arcs of type (nodeType(dest)), change * to trace_id. */ for (j = 0; j < list_length; j++) { Arc ac; ac = (Arc) sorted_list[j].ptr; if (arcType (ac) == bad_id) arcType (ac) = trace_id; } } else { /* * If dest is still a free node, it becomes the * trace tail. */ nodeStatus (dest) |= (VISITED | TRACE_TAIL); nodeType (dest) = trace_id; } } else if (nodeStatus (dest) & VISITED) { trace_id = nodeType (dest); arcType (arc) = trace_id; /* * Since src is a free node, src becomes a trace head. */ nodeStatus (src) |= (VISITED | TRACE_HEAD); nodeType (src) = trace_id; } else { trace_id = next_trace_id++; arcType (arc) = trace_id; nodeStatus (src) |= (VISITED | TRACE_HEAD); nodeType (src) = trace_id; nodeStatus (dest) |= (VISITED | TRACE_TAIL); nodeType (dest) = trace_id; } } /* * The remaining NOT_VISITED nodes, each forms a trace. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (nodeStatus (ptr) & VISITED) continue; nodeStatus (ptr) |= (VISITED | TRACE_HEAD | TRACE_TAIL); nodeType (ptr) = next_trace_id++; } /* * Detect inner loops. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (!(nodeStatus (ptr) & TRACE_TAIL)) continue; for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) { Node dest; dest = destinationNode (arc); if ((nodeStatus (dest) & TRACE_HEAD) && (nodeType (dest) == nodeType (ptr))) { nodeStatus (dest) |= LOOP_HEAD; break; } } } }
/** \brief parse the str_orig strig to read and save * information about the curent state of the network * \param str_orig string to parse (char *) * \param node_orig node which sent str_orig */ void Router::parseVector(char* str_orig, char* node_orig) { std::string sourceNode(node_orig); char *str = strcopy(str_orig + 1); // pour le [ str[strlen(str) - 1] = 0; // pour le ] std::vector<char*> v; // 1 : on extrait chaque groupe d'infos (séparés par ;) char * r = strtok(str, ";"); if(r != NULL) v.push_back(r); while((r = strtok(NULL, ";")) != NULL) { v.push_back(r); } // dans le tableau on a id,dist dans chaque case. // dans la routetable, il faut : // si le noeud est présent, mettre à jour la distance si elle est plus courte // sinon l'ajouter et mettre en next hop sourceNode std::vector<char*>::iterator i; RouteTable::iterator i_rte; for(i_rte = routeTable.begin(); i_rte != routeTable.end(); ++i_rte) { if((*i_rte).second.name() != (*i_rte).second.nextHop() && (*i_rte).second.nextHop() == sourceNode) { routeTable.erase(i_rte); } } // On ajoute ceux qui ne sont pas dans la table for(i = v.begin(); i != v.end(); ++i) { std::string s(strtok((*i), ",")); if(s != std::string(getName())) { int dist = atoi(strtok(NULL, ",")); if(routeTable.find(s) != routeTable.end()) // si on le trouve { if((routeTable[s].isNeighbor() && dist < routeTable[s].dist()) || (!routeTable[s].isNeighbor() && dist + routeTable[sourceNode].dist() < routeTable[s].dist()) || (!routeTable[s].isNeighbor() && routeTable[s].nextHop() == sourceNode && routeTable[s].dist() != dist + routeTable[sourceNode].dist()) || (routeTable[s].dist() < 0)) { routeTable[s].nextHop() = sourceNode; if(!routeTable[s].isNeighbor()) { routeTable[s].dist() = dist + routeTable[sourceNode].dist(); } else { routeTable[s].dist() = dist; } } } else { routeTable[s] = Entry(s, sourceNode, dist + routeTable[sourceNode].dist()); // exception si sourceNode pas dans hashtable ? peu probable } } } }