/**
     *   
     * @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);
      }
    }
Beispiel #2
0
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);
      }
    }