• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. circular traversing list

Stats

  • Locked Locked
  • Replies 3
  • Subscribers 142
  • Views 13960
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

circular traversing list

demsar
demsar over 7 years ago

Hi,

Is there an efficient way of implementing push functionality on a list (== circular traversing == removing last element and appending to the beginning of the list || removing first element and adding to the end of the list)?

List elements are not uniq. List can be very long, so I am searching for an efficient way.

I tried such implementation and it seems to be fine, just not sure, if the most efficient.

searchQueue1=lconc( nil list(1 2 3 4 5 6 7 8 9 ))

cadr(tconc(searchQueue1 popf(car(searchQueue1))))

and to reverse order:

searchQueue1=lconc(nil reverse(car(searchQueue1)))

cadr(tconc(searchQueue1 popf(car(searchQueue1))))

Please let me know, if there is a more efficient way of doing the same.

Thanks and best regards

Blaz

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 7 years ago

    Hi Blaz,

    That's likely to be as close to the most efficient (without thinking about it too much). tconc structures are quite efficient because they maintain a pointer to the last cell in the list, and so any time you need to get to the end of the list quickly, they are a good bet.

    Only requirement in your case is that the list is non-nil, but apart from that the efficiency is going to be good - probably I'd have to understand precisely how it's going to be used to know if there's any more optimal way of doing this. One approach (if the list of values is fixed) would be to use listToVector to convert the original list to an array and then have an index which cycled through (incrementing and taking the modulus with the length):

    defclass(CCFqueue ()
      (
        (vector @initarg list)
        (index @initform 0)
        (length)
      )
    )

    defmethod(initializeInstance @after ((obj CCFqueue) @rest _initArgs)
      obj->vector=listToVector(obj->vector)
      obj->length=length(obj->vector)
      t
    )

    defmethod(CCFnext ((obj CCFqueue))
      prog1(
        obj->vector[obj->index]
        obj->index=mod(obj->index+1 obj->length)
      )
    )

    You'd then use this:

    queue=CCFqueue(?list '(1 2 3 4 5 6 7 8 9)
    CCFnext(queue) => 1
    CCFnext(queue) => 2
    ...
    CCFnext(queue) => 9
    CCFnext(queue) => 1

    Without profiling it in the situation you specifically need it, I probably can't comment on whether this would be any better (it probably generates less garbage for garbage collection, but it does require the list to be fixed).

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 7 years ago

    Hi Blaz,

    That's likely to be as close to the most efficient (without thinking about it too much). tconc structures are quite efficient because they maintain a pointer to the last cell in the list, and so any time you need to get to the end of the list quickly, they are a good bet.

    Only requirement in your case is that the list is non-nil, but apart from that the efficiency is going to be good - probably I'd have to understand precisely how it's going to be used to know if there's any more optimal way of doing this. One approach (if the list of values is fixed) would be to use listToVector to convert the original list to an array and then have an index which cycled through (incrementing and taking the modulus with the length):

    defclass(CCFqueue ()
      (
        (vector @initarg list)
        (index @initform 0)
        (length)
      )
    )

    defmethod(initializeInstance @after ((obj CCFqueue) @rest _initArgs)
      obj->vector=listToVector(obj->vector)
      obj->length=length(obj->vector)
      t
    )

    defmethod(CCFnext ((obj CCFqueue))
      prog1(
        obj->vector[obj->index]
        obj->index=mod(obj->index+1 obj->length)
      )
    )

    You'd then use this:

    queue=CCFqueue(?list '(1 2 3 4 5 6 7 8 9)
    CCFnext(queue) => 1
    CCFnext(queue) => 2
    ...
    CCFnext(queue) => 9
    CCFnext(queue) => 1

    Without profiling it in the situation you specifically need it, I probably can't comment on whether this would be any better (it probably generates less garbage for garbage collection, but it does require the list to be fixed).

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • demsar
    demsar over 7 years ago in reply to Andrew Beckett

    Hi Andrew, 

    Thanks for super fast answer.

    I need to implement search forward/backward mechanism in treeTable (GUI).

    At the moment I create the list of treeTable elements (hiGetTreeItems, once) and then traverse through elements forward/backwards applying match check on every description (hiGetTreeItemDescription(eval(item))

    Working with indexes would be possible as well (increasing/decreasing the index). What is more efficient?

    Side notice: this is one example, but I was generally interested, how to efficiently implement push/pop mechanism, could use it elsewhere..

    Thanks and best regards

    Blaz

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 7 years ago in reply to demsar

    Hi Blaz,

    This is one of those things that I would probably have more than one attempt at implementing, and experiment with the profiler to determine which was the fastest. For example, it sounds as if you might be able to use a hash table, but maybe you only ever want to find a certain range of tree table items - so maybe that wouldn't be appropriate.

    Your push/pop isn't a traditional push/pop - which can easily be achieved with adding/removing elements from the beginning of a list. In your case you are not really pushing or popping - you're just cycling around the list. There's no doubly-linked list in SKILL (without creating one yourself) which sounds as if it might be one way. Creating a vector (array) on the fly might be an efficient way of doing this though - that really depends on whether the data keeps changing or is (reasonably) fixed - i.e. creating the vectors is a relatively infrequent operation.

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information