@@ -32,6 +32,7 @@ The implementation is loop based. It does not use recursion and does not have st
32
32
Complexity: worst-case `O(|V| + |E|)`.
33
33
34
34
Params:
35
+ RC = nogc mode, refcounted output
35
36
graph = components (ndslice) sorted in the direction of traversal of the graph. Each component is an array of indeces.
36
37
Returns:
37
38
components (ndslice of arrays of indexes)
@@ -44,7 +45,7 @@ See_also:
44
45
$(SUBREF utility, graph)
45
46
+/
46
47
pragma (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)
48
49
if (isUnsigned! I)
49
50
{
50
51
import mir.utility: min;
@@ -87,35 +88,49 @@ auto tarjan(G, I = Unqual!(ForeachType!(ForeachType!G)))(G graph)
87
88
}
88
89
}
89
90
90
- bool [] onStack = new bool [graph.length];
91
- I[] stack;
92
- IndexNode[] indeces;
93
- LoopNode[] loopStack;
94
- I index;
91
+
95
92
sizediff_t stackIndex;
96
93
sizediff_t backStackIndex = graph.length;
97
94
sizediff_t componentBackStackIndex = graph.length + 1 ;
98
95
99
- if (__ctfe )
96
+ static if (RC )
100
97
{
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 );
104
103
}
105
104
else
106
105
{
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;
109
122
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
+ }
114
128
}
115
129
116
130
foreach (ref node; indeces)
117
131
node.index = undefined;
118
132
133
+ I index;
119
134
foreach (size_t v; 0u .. graph.length)
120
135
{
121
136
if (indeces[v].isUndefined)
@@ -191,26 +206,42 @@ auto tarjan(G, I = Unqual!(ForeachType!(ForeachType!G)))(G graph)
191
206
}
192
207
}
193
208
194
- S[] pairwiseIndex ;
195
- if (__ctfe )
209
+ const indexLength = graph.length + 1 - componentBackStackIndex + 1 ;
210
+ static if (RC )
196
211
{
197
- pairwiseIndex = new S[graph.length - componentBackStackIndex + 1 ] ;
212
+ auto pairwiseIndex = RCArray ! S(indexLength, true ) ;
198
213
}
199
214
else
200
215
{
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
+ }
205
228
}
206
- foreach (i, ref e; loopStack[componentBackStackIndex .. $])
229
+ foreach (i, ref e; loopStack[][ componentBackStackIndex .. $])
207
230
{
208
231
pairwiseIndex[i] = e.index;
209
232
}
210
233
pairwiseIndex[$ - 1 ] = cast (I) graph.length;
211
234
212
235
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
+ }
214
245
}
215
246
216
247
/+ +
@@ -241,14 +272,21 @@ pure version(mir_test) unittest
241
272
" 11" : [],
242
273
].graphSeries;
243
274
244
- auto components = gs.data.tarjan;
245
275
246
- assert (components = = [
276
+ static immutable result = [
247
277
[0 ],
248
278
[1 , 2 , 5 , 4 , 3 , 6 ],
249
279
[10 ],
250
280
[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);
252
290
}
253
291
254
292
/+ +
0 commit comments