@@ -3,10 +3,53 @@ extern crate test;
3
3
use super :: * ;
4
4
use crate :: graph:: tests:: TestGraph ;
5
5
6
+ #[ derive( Copy , Clone , Debug ) ]
7
+ struct MaxReached ( usize ) ;
8
+ type UsizeSccs = Sccs < usize , usize , ( ) > ;
9
+ type MaxReachedSccs = Sccs < usize , usize , MaxReached > ;
10
+
11
+ impl Annotation for MaxReached {
12
+ fn merge_scc ( self , other : Self ) -> Self {
13
+ Self ( std:: cmp:: max ( other. 0 , self . 0 ) )
14
+ }
15
+
16
+ fn merge_reached ( self , other : Self ) -> Self {
17
+ self . merge_scc ( other)
18
+ }
19
+ }
20
+
21
+ impl PartialEq < usize > for MaxReached {
22
+ fn eq ( & self , other : & usize ) -> bool {
23
+ & self . 0 == other
24
+ }
25
+ }
26
+
27
+ impl MaxReached {
28
+ fn from_usize ( nr : usize ) -> Self {
29
+ Self ( nr)
30
+ }
31
+ }
32
+
33
+ #[ derive( Copy , Clone , Debug ) ]
34
+ struct MinMaxIn {
35
+ min : usize ,
36
+ max : usize ,
37
+ }
38
+
39
+ impl Annotation for MinMaxIn {
40
+ fn merge_scc ( self , other : Self ) -> Self {
41
+ Self { min : std:: cmp:: min ( self . min , other. min ) , max : std:: cmp:: max ( self . max , other. max ) }
42
+ }
43
+
44
+ fn merge_reached ( self , _other : Self ) -> Self {
45
+ self
46
+ }
47
+ }
48
+
6
49
#[ test]
7
50
fn diamond ( ) {
8
51
let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 3 ) , ( 2 , 3 ) ] ) ;
9
- let sccs: Sccs < _ , usize > = Sccs :: new ( & graph) ;
52
+ let sccs: UsizeSccs = Sccs :: new ( & graph) ;
10
53
assert_eq ! ( sccs. num_sccs( ) , 4 ) ;
11
54
assert_eq ! ( sccs. num_sccs( ) , 4 ) ;
12
55
}
@@ -34,7 +77,7 @@ fn test_big_scc() {
34
77
+-- 2 <--+
35
78
*/
36
79
let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 0 ) , ( 3 , 2 ) ] ) ;
37
- let sccs: Sccs < _ , usize > = Sccs :: new ( & graph) ;
80
+ let sccs: UsizeSccs = Sccs :: new ( & graph) ;
38
81
assert_eq ! ( sccs. num_sccs( ) , 1 ) ;
39
82
}
40
83
@@ -50,7 +93,7 @@ fn test_three_sccs() {
50
93
+-- 2 <--+
51
94
*/
52
95
let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 2 , 1 ) , ( 3 , 2 ) ] ) ;
53
- let sccs: Sccs < _ , usize > = Sccs :: new ( & graph) ;
96
+ let sccs: UsizeSccs = Sccs :: new ( & graph) ;
54
97
assert_eq ! ( sccs. num_sccs( ) , 3 ) ;
55
98
assert_eq ! ( sccs. scc( 0 ) , 1 ) ;
56
99
assert_eq ! ( sccs. scc( 1 ) , 0 ) ;
@@ -106,7 +149,7 @@ fn test_find_state_2() {
106
149
// 2 InCycleWith { 1 }
107
150
// 3 InCycleWith { 0 }
108
151
109
- let sccs: Sccs < _ , usize > = Sccs :: new ( & graph) ;
152
+ let sccs: UsizeSccs = Sccs :: new ( & graph) ;
110
153
assert_eq ! ( sccs. num_sccs( ) , 1 ) ;
111
154
assert_eq ! ( sccs. scc( 0 ) , 0 ) ;
112
155
assert_eq ! ( sccs. scc( 1 ) , 0 ) ;
@@ -130,7 +173,7 @@ fn test_find_state_3() {
130
173
*/
131
174
let graph =
132
175
TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 0 , 4 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 1 ) , ( 3 , 0 ) , ( 4 , 2 ) , ( 5 , 2 ) ] ) ;
133
- let sccs: Sccs < _ , usize > = Sccs :: new ( & graph) ;
176
+ let sccs: UsizeSccs = Sccs :: new ( & graph) ;
134
177
assert_eq ! ( sccs. num_sccs( ) , 2 ) ;
135
178
assert_eq ! ( sccs. scc( 0 ) , 0 ) ;
136
179
assert_eq ! ( sccs. scc( 1 ) , 0 ) ;
@@ -165,7 +208,7 @@ fn test_deep_linear() {
165
208
nodes. push ( ( i - 1 , i) ) ;
166
209
}
167
210
let graph = TestGraph :: new ( 0 , nodes. as_slice ( ) ) ;
168
- let sccs: Sccs < _ , usize > = Sccs :: new ( & graph) ;
211
+ let sccs: UsizeSccs = Sccs :: new ( & graph) ;
169
212
assert_eq ! ( sccs. num_sccs( ) , NR_NODES ) ;
170
213
assert_eq ! ( sccs. scc( 0 ) , NR_NODES - 1 ) ;
171
214
assert_eq ! ( sccs. scc( NR_NODES - 1 ) , 0 ) ;
@@ -210,7 +253,164 @@ fn bench_sccc(b: &mut test::Bencher) {
210
253
graph[ 21 ] = ( 7 , 4 ) ;
211
254
let graph = TestGraph :: new ( 0 , & graph[ ..] ) ;
212
255
b. iter ( || {
213
- let sccs: Sccs < _ , usize > = Sccs :: new ( & graph) ;
256
+ let sccs: UsizeSccs = Sccs :: new ( & graph) ;
214
257
assert_eq ! ( sccs. num_sccs( ) , 3 ) ;
215
258
} ) ;
216
259
}
260
+
261
+ #[ test]
262
+ fn test_max_self_loop ( ) {
263
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 0 ) ] ) ;
264
+ let sccs: MaxReachedSccs =
265
+ Sccs :: new_with_annotation ( & graph, |n| if n == 0 { MaxReached ( 17 ) } else { MaxReached ( 0 ) } ) ;
266
+ assert_eq ! ( sccs. annotation( 0 ) , 17 ) ;
267
+ }
268
+
269
+ #[ test]
270
+ fn test_max_branch ( ) {
271
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 3 ) , ( 2 , 4 ) ] ) ;
272
+ let sccs: MaxReachedSccs = Sccs :: new_with_annotation ( & graph, MaxReached :: from_usize) ;
273
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) , 4 ) ;
274
+ assert_eq ! ( sccs. annotation( sccs. scc( 1 ) ) , 3 ) ;
275
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) , 4 ) ;
276
+ }
277
+ #[ test]
278
+ fn test_single_cycle_max ( ) {
279
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 2 ) , ( 2 , 3 ) , ( 2 , 4 ) , ( 4 , 1 ) , ( 1 , 2 ) ] ) ;
280
+ let sccs: MaxReachedSccs = Sccs :: new_with_annotation ( & graph, MaxReached :: from_usize) ;
281
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) , 4 ) ;
282
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) , 4 ) ;
283
+ }
284
+
285
+ #[ test]
286
+ fn test_simple_cycle_max ( ) {
287
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 2 , 0 ) ] ) ;
288
+ let sccs: MaxReachedSccs = Sccs :: new_with_annotation ( & graph, MaxReached :: from_usize) ;
289
+ assert_eq ! ( sccs. num_sccs( ) , 1 ) ;
290
+ }
291
+
292
+ #[ test]
293
+ fn test_double_cycle_max ( ) {
294
+ let graph =
295
+ TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 1 , 4 ) , ( 2 , 3 ) , ( 2 , 4 ) , ( 3 , 5 ) , ( 4 , 1 ) , ( 5 , 4 ) ] ) ;
296
+ let sccs: MaxReachedSccs =
297
+ Sccs :: new_with_annotation ( & graph, |n| if n == 5 { MaxReached ( 2 ) } else { MaxReached ( 1 ) } ) ;
298
+
299
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) . 0 , 2 ) ;
300
+ }
301
+
302
+ #[ test]
303
+ fn test_bug_minimised ( ) {
304
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 3 ) , ( 0 , 1 ) , ( 3 , 2 ) , ( 2 , 3 ) , ( 1 , 4 ) , ( 4 , 5 ) , ( 5 , 4 ) ] ) ;
305
+ let sccs: MaxReachedSccs = Sccs :: new_with_annotation ( & graph, |n| match n {
306
+ 3 => MaxReached ( 1 ) ,
307
+ _ => MaxReached ( 0 ) ,
308
+ } ) ;
309
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) , 1 ) ;
310
+ assert_eq ! ( sccs. annotation( sccs. scc( 1 ) ) , 0 ) ;
311
+ assert_eq ! ( sccs. annotation( sccs. scc( 4 ) ) , 0 ) ;
312
+ }
313
+
314
+ #[ test]
315
+ fn test_bug_max_leak_minimised ( ) {
316
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 3 ) , ( 3 , 0 ) , ( 3 , 4 ) , ( 4 , 3 ) ] ) ;
317
+ let sccs: MaxReachedSccs = Sccs :: new_with_annotation ( & graph, |w| match w {
318
+ 4 => MaxReached ( 1 ) ,
319
+ _ => MaxReached ( 0 ) ,
320
+ } ) ;
321
+
322
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) , 0 ) ;
323
+ assert_eq ! ( sccs. annotation( sccs. scc( 3 ) ) , 1 ) ;
324
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) , 1 ) ;
325
+ }
326
+
327
+ #[ test]
328
+ fn test_bug_max_leak ( ) {
329
+ let graph = TestGraph :: new (
330
+ 8 ,
331
+ & [
332
+ ( 0 , 0 ) ,
333
+ ( 0 , 18 ) ,
334
+ ( 0 , 19 ) ,
335
+ ( 0 , 1 ) ,
336
+ ( 0 , 2 ) ,
337
+ ( 0 , 7 ) ,
338
+ ( 0 , 8 ) ,
339
+ ( 0 , 23 ) ,
340
+ ( 18 , 0 ) ,
341
+ ( 18 , 12 ) ,
342
+ ( 19 , 0 ) ,
343
+ ( 19 , 25 ) ,
344
+ ( 12 , 18 ) ,
345
+ ( 12 , 3 ) ,
346
+ ( 12 , 5 ) ,
347
+ ( 3 , 12 ) ,
348
+ ( 3 , 21 ) ,
349
+ ( 3 , 22 ) ,
350
+ ( 5 , 13 ) ,
351
+ ( 21 , 3 ) ,
352
+ ( 22 , 3 ) ,
353
+ ( 13 , 5 ) ,
354
+ ( 13 , 4 ) ,
355
+ ( 4 , 13 ) ,
356
+ ( 4 , 0 ) ,
357
+ ( 2 , 11 ) ,
358
+ ( 7 , 6 ) ,
359
+ ( 6 , 20 ) ,
360
+ ( 20 , 6 ) ,
361
+ ( 8 , 17 ) ,
362
+ ( 17 , 9 ) ,
363
+ ( 9 , 16 ) ,
364
+ ( 16 , 26 ) ,
365
+ ( 26 , 15 ) ,
366
+ ( 15 , 10 ) ,
367
+ ( 10 , 14 ) ,
368
+ ( 14 , 27 ) ,
369
+ ( 23 , 24 ) ,
370
+ ] ,
371
+ ) ;
372
+ let sccs: MaxReachedSccs = Sccs :: new_with_annotation ( & graph, |w| match w {
373
+ 22 => MaxReached ( 1 ) ,
374
+ 24 => MaxReached ( 2 ) ,
375
+ 27 => MaxReached ( 2 ) ,
376
+ _ => MaxReached ( 0 ) ,
377
+ } ) ;
378
+
379
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) , 0 ) ;
380
+ assert_eq ! ( sccs. annotation( sccs. scc( 7 ) ) , 0 ) ;
381
+ assert_eq ! ( sccs. annotation( sccs. scc( 8 ) ) , 2 ) ;
382
+ assert_eq ! ( sccs. annotation( sccs. scc( 23 ) ) , 2 ) ;
383
+ assert_eq ! ( sccs. annotation( sccs. scc( 3 ) ) , 2 ) ;
384
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) , 2 ) ;
385
+ }
386
+
387
+ #[ test]
388
+ fn test_bug_max_zero_stick_shape ( ) {
389
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 1 , 2 ) , ( 2 , 3 ) , ( 3 , 2 ) , ( 3 , 4 ) ] ) ;
390
+
391
+ let sccs: MaxReachedSccs = Sccs :: new_with_annotation ( & graph, |w| match w {
392
+ 4 => MaxReached ( 1 ) ,
393
+ _ => MaxReached ( 0 ) ,
394
+ } ) ;
395
+
396
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) , 1 ) ;
397
+ assert_eq ! ( sccs. annotation( sccs. scc( 1 ) ) , 1 ) ;
398
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) , 1 ) ;
399
+ assert_eq ! ( sccs. annotation( sccs. scc( 3 ) ) , 1 ) ;
400
+ assert_eq ! ( sccs. annotation( sccs. scc( 4 ) ) , 1 ) ;
401
+ }
402
+
403
+ #[ test]
404
+ fn test_min_max_in ( ) {
405
+ let graph = TestGraph :: new ( 0 , & [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 3 ) , ( 3 , 0 ) , ( 3 , 4 ) , ( 4 , 3 ) , ( 3 , 5 ) ] ) ;
406
+ let sccs: Sccs < usize , usize , MinMaxIn > =
407
+ Sccs :: new_with_annotation ( & graph, |w| MinMaxIn { min : w, max : w } ) ;
408
+
409
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) . min, 2 ) ;
410
+ assert_eq ! ( sccs. annotation( sccs. scc( 2 ) ) . max, 2 ) ;
411
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) . min, 0 ) ;
412
+ assert_eq ! ( sccs. annotation( sccs. scc( 0 ) ) . max, 4 ) ;
413
+ assert_eq ! ( sccs. annotation( sccs. scc( 3 ) ) . min, 0 ) ;
414
+ assert_eq ! ( sccs. annotation( sccs. scc( 3 ) ) . max, 4 ) ;
415
+ assert_eq ! ( sccs. annotation( sccs. scc( 5 ) ) . min, 5 ) ;
416
+ }
0 commit comments