@@ -1637,7 +1637,7 @@ pub mod iter {
16371637 use super :: {
16381638 Connection , DrivenNet , InputPort , Instantiable , Net , NetRef , Netlist , Operand , WeakIndex ,
16391639 } ;
1640- use std:: collections:: HashSet ;
1640+ use std:: collections:: { HashMap , HashSet } ;
16411641 /// An iterator over the nets in a netlist
16421642 pub struct NetIterator < ' a , I : Instantiable > {
16431643 netlist : & ' a Netlist < I > ,
@@ -1772,6 +1772,51 @@ pub mod iter {
17721772 }
17731773 }
17741774
1775+ /// A stack that can check contains in roughly O(1) time.
1776+ struct Stack < T : std:: hash:: Hash + PartialEq + Eq + Clone > {
1777+ stack : Vec < T > ,
1778+ counter : HashMap < T , usize > ,
1779+ }
1780+
1781+ impl < T > Stack < T >
1782+ where
1783+ T : std:: hash:: Hash + PartialEq + Eq + Clone ,
1784+ {
1785+ /// Create a new, empty Stack.
1786+ fn new ( ) -> Self {
1787+ Self {
1788+ stack : Vec :: new ( ) ,
1789+ counter : HashMap :: new ( ) ,
1790+ }
1791+ }
1792+
1793+ /// Inserts an element into the stack
1794+ fn push ( & mut self , item : T ) {
1795+ self . stack . push ( item. clone ( ) ) ;
1796+ * self . counter . entry ( item) . or_insert ( 0 ) += 1 ;
1797+ }
1798+
1799+ /// Pops the top element from the stack
1800+ fn pop ( & mut self ) -> Option < T > {
1801+ if let Some ( item) = self . stack . pop ( ) {
1802+ if let Some ( count) = self . counter . get_mut ( & item) {
1803+ * count -= 1 ;
1804+ if * count == 0 {
1805+ self . counter . remove ( & item) ;
1806+ }
1807+ }
1808+ Some ( item)
1809+ } else {
1810+ None
1811+ }
1812+ }
1813+
1814+ /// Checks if the stack contains the given element
1815+ fn contains ( & self , item : & T ) -> bool {
1816+ self . counter . contains_key ( item)
1817+ }
1818+ }
1819+
17751820 /// A depth-first iterator over the circuit nodes in a netlist
17761821 /// # Examples
17771822 ///
@@ -1792,7 +1837,7 @@ pub mod iter {
17921837 /// ```
17931838 pub struct DFSIterator < ' a , I : Instantiable > {
17941839 netlist : & ' a Netlist < I > ,
1795- stack : Vec < NetRef < I > > ,
1840+ stack : Stack < NetRef < I > > ,
17961841 visited : HashSet < usize > ,
17971842 cycles : bool ,
17981843 }
@@ -1803,9 +1848,11 @@ pub mod iter {
18031848 {
18041849 /// Create a new DFS iterator for the netlist starting at `from`.
18051850 pub fn new ( netlist : & ' a Netlist < I > , from : NetRef < I > ) -> Self {
1851+ let mut s = Stack :: new ( ) ;
1852+ s. push ( from) ;
18061853 Self {
18071854 netlist,
1808- stack : vec ! [ from ] ,
1855+ stack : s ,
18091856 visited : HashSet :: new ( ) ,
18101857 cycles : false ,
18111858 }
@@ -1847,16 +1894,20 @@ pub mod iter {
18471894 if let Some ( item) = self . stack . pop ( ) {
18481895 let uw = item. clone ( ) . unwrap ( ) ;
18491896 let index = uw. borrow ( ) . get_index ( ) ;
1850- if !self . visited . insert ( index) {
1851- self . cycles = true ;
1852- return self . next ( ) ;
1853- }
1854- let operands = & uw. borrow ( ) . operands ;
1855- for operand in operands. iter ( ) . flatten ( ) {
1856- self . stack
1857- . push ( NetRef :: wrap ( self . netlist . index_weak ( & operand. root ( ) ) ) ) ;
1897+ if self . visited . insert ( index) {
1898+ let operands = & uw. borrow ( ) . operands ;
1899+ for operand in operands. iter ( ) . flatten ( ) {
1900+ self . stack
1901+ . push ( NetRef :: wrap ( self . netlist . index_weak ( & operand. root ( ) ) ) ) ;
1902+ }
18581903 }
1859- return Some ( item) ;
1904+
1905+ return if self . stack . contains ( & item) {
1906+ self . cycles = true ;
1907+ self . next ( )
1908+ } else {
1909+ Some ( item)
1910+ } ;
18601911 }
18611912
18621913 None
0 commit comments