// -*- C++ -*- (c) 2013 Vladimír Štill #if GEN_EXPLICIT || ALG_EXPLICIT #include #include #include #include #ifndef DIVINE_COMPACT_TRANSPOSE_H #define DIVINE_COMPACT_TRANSPOSE_H namespace divine { namespace dess { template< typename EdgeSpec > void transpose( DataBlock &from, DataBlock &to ) { #if 0 static_assert( std::is_same< typename std::result_of< dectype( &EdgeSpec::index() )( EdgeSpec ) >::type, int64_t & >::value, "Invalid EdgeSpec passed (expected method `int64_t &index()'" ); #endif ASSERT_EQ( from.count(), to.count() ); int64_t *counts = to.lowLevelIndices(); std::memset( counts, 0, from.count() * sizeof( int64_t ) ); // count outdegree ASSERT_EQ( from.size( 0 ) % sizeof( EdgeSpec ), 0u ); counts[ 0 ] = from.size( 0 ) / sizeof( EdgeSpec ); // intials EdgeSpec *revEdges = reinterpret_cast< EdgeSpec * >( from[ 1 ] ); EdgeSpec *revEdgesEnd = reinterpret_cast< EdgeSpec * >( from[ from.count() ] ); for ( EdgeSpec *p = revEdges; p < revEdgesEnd; ++p ) ++counts[ p->index() ]; auto inserter = to.inserter(); // copy initials inserter.emplace( counts[ 0 ] * sizeof( EdgeSpec ), [&]( char *ptr, int64_t ) { std::copy( from[ 0 ], from[ 1 ], ptr ); } ); // distribute space as needed for ( int64_t i = 1; i < to.count(); ++i ) inserter.emplace( counts[ i ] * sizeof( EdgeSpec ), []( char *ptr, int64_t size ) { std::memset( ptr, 0, size ); } ); // transpose for ( int i = 1; i < from.count(); ++i ) from.map< EdgeSpec >( i )( [ &to, i ]( EdgeSpec *edges, int64_t size ) { for ( int64_t j = 0; j < size; ++j ) to.map< EdgeSpec >( edges[ j ].index() ) ( [ edges, i, j ]( EdgeSpec *de, int64_t size ) { auto last = de + size - 1; for ( ; de->index(); ++de ) ASSERT_LEQ( de, last ); static_cast< void >( last ); de->index() = i; de->label() = edges[ j ].label(); } ); } ); } } } #endif // DIVINE_COMPACT_TRANSPOSE_H #endif