/** * * @brief creates transitions for 'dup' mirroring 'orig' outgoing transitions * * @param - orig: the state that is being duplicated * @param - dup: the state that is duplicating 'orig' * */ void TransitionStorage::dupTransOutgoing( State orig, State dup ) { // Duplicate outgoing internal transitions. const Info::Internals & from = T_info.fromTrans(orig); for( Info::InternalIterator it = from.begin(); it != from.end(); it++ ) { Internal iTrans(dup,getInternalSym(*it),getTarget(*it)); addInternal(iTrans); } // Duplicate call site call transitions. const Info::Calls & call = T_info.callTrans(orig); for( Info::CallIterator it = call.begin(); it != call.end(); it++ ) { Call cTrans(dup,getCallSym(*it),getEntry(*it)); addCall(cTrans); } // Duplicate exit point return transitions. const Info::Returns & exit = T_info.exitTrans(orig); for( Info::ReturnIterator it = exit.begin(); it != exit.end(); it++ ) { Return rTrans(dup,getCallSite(*it),getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); } // Q: Do we want to do these? Seems inconsistent. -Evan // A: Aditya says 'yes', and thinks we need it. So we definitely don't // want to change it without looking at uses and compensating. // Duplicate call predecessor return transitions. const Info::Returns & pred = T_info.predTrans(orig); for( Info::ReturnIterator it = pred.begin(); it != pred.end(); it++ ) { Return rTrans(getExit(*it),dup,getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); } }
int follow(float level, CONTOUR_POINT *point) { int segment, start_heading, exitFace, adj, opp; float fadj,fopp; exitFace = CONTOUR_UNKNOWN; segment = -1; start_heading = point->heading; while (segment == -1) { /* SAVE PRESENT POINT IF VALID */ if (savePoint(level,point)) { /* HAS THE CONTOUR CLOSED */ if (!(faceInUse(point,CONTOUR_SAME))) { markInUse(point); /* HAS THE CONTOUR REACHED AN EDGE */ if (cellExists(point)) { /* COMPUTE THE EXIT FACE RELATIVE TO THE PRESENT FACE */ fadj = getDataPoint(point,CONTOUR_ADJACENT); fopp = getDataPoint(point,CONTOUR_OPPOSITE); adj = (fadj > level) ? 2 : 0; opp = (fopp <= level) ? 1 : 0; switch (adj+opp) { case 0: exitFace = CONTOUR_OPPOSITE; break; case 1: exitFace = CONTOUR_NEXT; break; case 2: exitFace = CONTOUR_ADJACENT; break; case 3: exitFace = getExit(level,point); break; } if (exitFace == CONTOUR_UNKNOWN) { point->heading = start_heading; } else { point->heading = (point->heading + exitFace + 2) % 4; } /* UPDATE THE INDEXES BASE ON THE NEW HEADING */ switch (point->heading) { case CONTOUR_EAST: point->x++; break; case CONTOUR_NORTH: point->y++; break; case CONTOUR_WEST: point->x--; break; case CONTOUR_SOUTH: point->y--; break; } } else { /* CONTOUR HAS REACHED AN EDGE, EXIT */ segment = CONTOUR_FALSE; } } else { /* CONTOUR HAS CLOSED, EXIT */ segment = CONTOUR_FALSE; } } else { /* CONTOUR IS SEGMENTED BY INVALID DATA OR MAX CONTOUR POINTS */ segment = CONTOUR_TRUE; } } return segment; }
/** * * @brief print the collection of transitions * * @param - o: the output stream to print to * @return the output stream that was printed to * */ std::ostream & TransitionStorage::print( std::ostream & o ) const { //Print call transitions. o << "Delta_c: {\n "; bool first = true; for( CallIterator cit = callTrans.begin(); cit != callTrans.end(); cit++, first=false ) { if( !first ) o << ", \n "; o << "("; printKey(o,getCallSite(*cit)); o << " (=" << getCallSite(*cit) << ") "; o << ", "; printKey(o,getCallSym(*cit)); o << ", "; printKey(o,getEntry(*cit)); o << " (=" << getEntry(*cit) << ") "; o << ")"; } o << "\n}\n"; //Print internal transitions. o << "Delta_i: {\n "; first = true; for(InternalIterator iit = internalTrans.begin(); iit != internalTrans.end(); iit++, first=false ) { if( !first ) o << ",\n "; o << "("; printKey(o,getSource(*iit)); o << " (=" << getSource(*iit) << ") "; o << ", "; printKey(o,getInternalSym(*iit)); o << ", "; printKey(o,getTarget(*iit)); o << " (=" << getTarget(*iit) << ") "; o << ")"; } o << "\n}\n"; //Print return transitions. o << "Delta_r: {\n "; first = true; for(ReturnIterator rit = returnTrans.begin(); rit != returnTrans.end(); rit++, first = false ) { if( !first ) o << ",\n "; o << "("; printKey(o,getExit(*rit)); o << " (=" << getExit(*rit) << ") "; o << ", "; printKey(o,getCallSite(*rit)); o << " (=" << getCallSite(*rit) << ") "; o << ", "; printKey(o,getReturnSym(*rit)); o << ", "; printKey(o,getReturnSite(*rit)); o << " (=" << getReturnSite(*rit) << ") "; o << ")"; } o << "\n}\n"; return o; }
/** * * @brief creates transitions for 'dup' mirroring 'orig' transitions * * @param - orig: the state that is being duplicated * @param - dup: the state that is duplicating 'orig' * */ void TransitionStorage::dupTrans( State orig, State dup ) { //Duplicate outgoing internal transitions. const Info::Internals & from = T_info.fromTrans(orig); for( Info::InternalIterator it = from.begin(); it != from.end(); it++ ) { Internal iTrans(dup,getInternalSym(*it),getTarget(*it)); addInternal(iTrans); // Q: This is also inconsistent with dupTransOutgoing, which didn't do // anything special with self loops. -Evan // A: Aditya says yes, but this is again what McVeto(?) needs. // dupTrans is used in 'duplicateState', but dupTransOutgoing is // different. if( orig == getTarget(*it) ) //Handle self-loops. { Internal loop(dup,getInternalSym(*it),dup); addInternal(loop); } } //Duplicate incoming internal transitions. const Info::Internals & to = T_info.toTrans(orig); for( Info::InternalIterator it = to.begin(); it != to.end(); it++ ) { Internal iTrans(getSource(*it),getInternalSym(*it),dup); addInternal(iTrans); } //Duplicate call site call transitions. const Info::Calls & call = T_info.callTrans(orig); for( Info::CallIterator it = call.begin(); it != call.end(); it++ ) { Call cTrans(dup,getCallSym(*it),getEntry(*it)); addCall(cTrans); if( orig == getEntry(*it) ) //Handle self-loops. { Call loop(dup,getCallSym(*it),dup); addCall(loop); } } //Duplicate entry point call transitions. const Info::Calls & entry = T_info.entryTrans(orig); for( Info::CallIterator it = entry.begin(); it != entry.end(); it++ ) { Call cTrans(getCallSite(*it),getCallSym(*it),dup); addCall(cTrans); } //Duplicate exit point return transitions. const Info::Returns & exit = T_info.exitTrans(orig); for( Info::ReturnIterator it = exit.begin(); it != exit.end(); it++ ) { Return rTrans(dup,getCallSite(*it),getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); if( orig == getCallSite(*it) ) //Handle self-loops. { Return loop(dup,dup,getReturnSym(*it),getReturnSite(*it)); addReturn(loop); } if( orig == getReturnSite(*it) ) //Handle self-loops. { Return loop(dup,getCallSite(*it),getReturnSym(*it),dup); addReturn(loop); } if( orig == getCallSite(*it) && orig == getReturnSite(*it) ) //Handle self-loops. { Return loop(dup,dup,getReturnSym(*it),dup); addReturn(loop); } } //Duplicate call predecessor return transitions. const Info::Returns & pred = T_info.predTrans(orig); for( Info::ReturnIterator it = pred.begin(); it != pred.end(); it++ ) { Return rTrans(getExit(*it),dup,getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); if( orig == getReturnSite(*it) ) //Handle self-loops. { Return loop(getExit(*it),dup,getReturnSym(*it),dup); addReturn(loop); } } //Duplicate return site return transitions. const Info::Returns & ret = T_info.retTrans(orig); for( Info::ReturnIterator it = ret.begin(); it != ret.end(); it++ ) { Return rTrans(getExit(*it),getCallSite(*it),getReturnSym(*it),dup); addReturn(rTrans); } }