@@ -426,25 +426,104 @@ pub trait RandomAccessLabeling: SequentialLabeling {
426
426
fn outdegree ( & self , node_id : usize ) -> usize ;
427
427
}
428
428
429
+ /// Error types that can occur during checking the implementation of a random
430
+ /// access labeling.
431
+ #[ derive( Error , Debug , Clone , PartialEq , Eq ) ]
432
+ pub enum CheckImplError {
433
+ /// The number of nodes returned by [`iter`](SequentialLabeling::iter)
434
+ /// is different from the number returned by
435
+ /// [`num_nodes`](SequentialLabeling::num_nodes).
436
+ #[ error( "Different number of nodes: {iter} (iter) != {method} (num_nodes)" ) ]
437
+ NumNodes { iter : usize , method : usize } ,
438
+
439
+ /// The number of successors returned by [`iter`](SequentialLabeling::iter)
440
+ /// is different from the number returned by
441
+ /// [`num_arcs`](RandomAccessLabeling::num_arcs).
442
+ #[ error( "Different number of nodes: {iter} (iter) != {method} (num_arcs)" ) ]
443
+ NumArcs { iter : u64 , method : u64 } ,
444
+
445
+ /// The two implementations return different labels for a specific node.
446
+ #[ error( "Different successors for node {node}: at index {index} {sequential} (sequential) != {random_access} (random access)" ) ]
447
+ Successors {
448
+ node : usize ,
449
+ index : usize ,
450
+ sequential : String ,
451
+ random_access : String ,
452
+ } ,
453
+
454
+ /// The graphs have different outdegrees for a specific node.
455
+ #[ error( "Different outdegree for node {node}: {sequential} (sequential) != {random_access} (random access)" ) ]
456
+ Outdegree {
457
+ node : usize ,
458
+ sequential : usize ,
459
+ random_access : usize ,
460
+ } ,
461
+ }
462
+
429
463
/// Checks the sequential vs. random-access implementation of a sorted
430
464
/// random-access labeling.
431
465
///
432
466
/// Note that this method will check that the sequential and random-access
433
467
/// iterators on labels of each node are identical, and that the number of
434
468
/// nodes returned by the sequential iterator is the same as the number of
435
469
/// nodes returned by [`num_nodes`](SequentialLabeling::num_nodes).
436
- pub fn check_impl < L : RandomAccessLabeling > ( l : L ) -> bool
470
+ pub fn check_impl < L : RandomAccessLabeling > ( l : L ) -> Result < ( ) , CheckImplError >
437
471
where
438
- L :: Label : PartialEq ,
472
+ L :: Label : PartialEq + std :: fmt :: Debug ,
439
473
{
440
474
let mut num_nodes = 0 ;
441
- for_ ! ( ( node, succ) in l. iter( ) {
475
+ let mut num_arcs: u64 = 0 ;
476
+ for_ ! ( ( node, succ_iter) in l. iter( ) {
442
477
num_nodes += 1 ;
443
- if !succ. into_iter( ) . eq( l. labels( node) . into_iter( ) ) {
444
- return false ;
478
+ let mut succ_iter = succ_iter. into_iter( ) ;
479
+ let mut succ = l. labels( node) . into_iter( ) ;
480
+ let mut index = 0 ;
481
+ loop {
482
+ match ( succ_iter. next( ) , succ. next( ) ) {
483
+ ( None , None ) => break ,
484
+ ( Some ( s0) , Some ( s1) ) => {
485
+ if s0 != s1 {
486
+ return Err ( CheckImplError :: Successors {
487
+ node,
488
+ index,
489
+ sequential: format!( "{:?}" , s0) ,
490
+ random_access: format!( "{:?}" , s1) ,
491
+ } ) ;
492
+ }
493
+ }
494
+ ( None , Some ( _) ) => {
495
+ return Err ( CheckImplError :: Outdegree {
496
+ node,
497
+ sequential: index,
498
+ random_access: index + 1 + succ. count( ) ,
499
+ } ) ;
500
+ }
501
+ ( Some ( _) , None ) => {
502
+ return Err ( CheckImplError :: Outdegree {
503
+ node,
504
+ sequential: index + 1 + succ_iter. count( ) ,
505
+ random_access: index,
506
+ } ) ;
507
+ }
508
+ }
509
+ index += 1 ;
445
510
}
511
+ num_arcs += index as u64 ;
446
512
} ) ;
447
- num_nodes == l. num_nodes ( )
513
+
514
+ if num_nodes != l. num_nodes ( ) {
515
+ Err ( CheckImplError :: NumNodes {
516
+ method : l. num_nodes ( ) ,
517
+ iter : num_nodes,
518
+ } )
519
+ } else if num_arcs != l. num_arcs ( ) {
520
+ Err ( CheckImplError :: NumArcs {
521
+ method : l. num_arcs ( ) ,
522
+ iter : num_arcs,
523
+ } )
524
+ } else {
525
+ Ok ( ( ) )
526
+ }
448
527
}
449
528
450
529
/// A struct used to make it easy to implement sequential access
0 commit comments