@@ -32,6 +32,7 @@ The implementation is loop based. It does not use recursion and does not have st
3232Complexity: worst-case `O(|V| + |E|)`.
3333
3434Params:
35+ RC = nogc mode, refcounted output
3536 graph = components (ndslice) sorted in the direction of traversal of the graph. Each component is an array of indeces.
3637Returns:
3738 components (ndslice of arrays of indexes)
@@ -44,7 +45,7 @@ See_also:
4445 $(SUBREF utility, graph)
4546+/
4647pragma (inline, false )
47- auto tarjan (G, I = Unqual! (ForeachType! (ForeachType! G)))(G graph)
48+ auto tarjan (bool RC = false , G, I = Unqual! (ForeachType! (ForeachType! G)))(G graph)
4849 if (isUnsigned! I)
4950{
5051 import mir.utility: min;
@@ -87,35 +88,49 @@ auto tarjan(G, I = Unqual!(ForeachType!(ForeachType!G)))(G graph)
8788 }
8889 }
8990
90- bool [] onStack = new bool [graph.length];
91- I[] stack;
92- IndexNode[] indeces;
93- LoopNode[] loopStack;
94- I index;
91+
9592 sizediff_t stackIndex;
9693 sizediff_t backStackIndex = graph.length;
9794 sizediff_t componentBackStackIndex = graph.length + 1 ;
9895
99- if (__ctfe )
96+ static if (RC )
10097 {
101- stack = new I[graph.length];
102- indeces = new IndexNode[graph.length];
103- loopStack = new LoopNode[componentBackStackIndex];
98+ import mir.rc.array;
99+ auto onStack = RCArray! bool (graph.length);
100+ auto stack = RCArray! I(graph.length, true );
101+ auto indeces = RCArray! IndexNode(graph.length, true );
102+ auto loopStack = RCArray! LoopNode(componentBackStackIndex, true );
104103 }
105104 else
106105 {
107- () @trusted {
108- import std.array : uninitializedArray;
106+ I[] stack;
107+ IndexNode[] indeces;
108+ LoopNode[] loopStack;
109+
110+ bool [] onStack = new bool [graph.length];
111+ if (__ctfe)
112+ {
113+
114+ stack = new I[graph.length];
115+ indeces = new IndexNode[graph.length];
116+ loopStack = new LoopNode[componentBackStackIndex];
117+ }
118+ else
119+ {
120+ () @trusted {
121+ import std.array : uninitializedArray;
109122
110- stack = uninitializedArray! (I[])(graph.length);
111- indeces = uninitializedArray! (IndexNode[])(graph.length);
112- loopStack = uninitializedArray! (LoopNode[])(componentBackStackIndex);
113- } ();
123+ stack = uninitializedArray! (I[])(graph.length);
124+ indeces = uninitializedArray! (IndexNode[])(graph.length);
125+ loopStack = uninitializedArray! (LoopNode[])(componentBackStackIndex);
126+ } ();
127+ }
114128 }
115129
116130 foreach (ref node; indeces)
117131 node.index = undefined;
118132
133+ I index;
119134 foreach (size_t v; 0u .. graph.length)
120135 {
121136 if (indeces[v].isUndefined)
@@ -191,26 +206,42 @@ auto tarjan(G, I = Unqual!(ForeachType!(ForeachType!G)))(G graph)
191206 }
192207 }
193208
194- S[] pairwiseIndex ;
195- if (__ctfe )
209+ const indexLength = graph.length + 1 - componentBackStackIndex + 1 ;
210+ static if (RC )
196211 {
197- pairwiseIndex = new S[graph.length - componentBackStackIndex + 1 ] ;
212+ auto pairwiseIndex = RCArray ! S(indexLength, true ) ;
198213 }
199214 else
200215 {
201- () @trusted {
202- import std.array : uninitializedArray;
203- pairwiseIndex = uninitializedArray! (S[])(graph.length + 1 - componentBackStackIndex + 1 );
204- } ();
216+ S[] pairwiseIndex;
217+ if (__ctfe)
218+ {
219+ pairwiseIndex = new S[indexLength];
220+ }
221+ else
222+ {
223+ () @trusted {
224+ import std.array : uninitializedArray;
225+ pairwiseIndex = uninitializedArray! (S[])(indexLength);
226+ } ();
227+ }
205228 }
206- foreach (i, ref e; loopStack[componentBackStackIndex .. $])
229+ foreach (i, ref e; loopStack[][ componentBackStackIndex .. $])
207230 {
208231 pairwiseIndex[i] = e.index;
209232 }
210233 pairwiseIndex[$ - 1 ] = cast (I) graph.length;
211234
212235 import mir.ndslice.topology: chopped;
213- return (()@trusted {return stack.ptr; }()).chopped(pairwiseIndex);
236+ static if (RC )
237+ {
238+ import core.lifetime : move;
239+ return chopped (RCI ! I(stack.move), pairwiseIndex.asSlice);
240+ }
241+ else
242+ {
243+ return (()@trusted {return stack.ptr; }()).chopped(pairwiseIndex);
244+ }
214245}
215246
216247/+ +
@@ -241,14 +272,21 @@ pure version(mir_test) unittest
241272 " 11" : [],
242273 ].graphSeries;
243274
244- auto components = gs.data.tarjan;
245275
246- assert (components = = [
276+ static immutable result = [
247277 [0 ],
248278 [1 , 2 , 5 , 4 , 3 , 6 ],
249279 [10 ],
250280 [7 , 8 , 9 ],
251- [11 ]]);
281+ [11 ]];
282+
283+ // chec GC interface
284+ auto components = gs.data.tarjan;
285+ assert (components == result);
286+ // check @nogc interface
287+ // Note: The lambda function is used here to show @nogc mode explicitly.
288+ auto rccomponents = (() @nogc => gs.data.tarjan! true )();
289+ assert (rccomponents == result);
252290}
253291
254292/+ +
0 commit comments