diff --git a/include/alp/reference/vector.hpp b/include/alp/reference/vector.hpp index 979b30049..28c414728 100644 --- a/include/alp/reference/vector.hpp +++ b/include/alp/reference/vector.hpp @@ -414,6 +414,11 @@ namespace alp { typedef Vector< T, structures::General, Density::Dense, view::Gather< self_type >, imf::Strided, imf::Id, reference > type; }; + template < bool d > + struct view_type< view::matrix, d > { + typedef Matrix< T, structures::General, Density::Dense, view::Matrix< self_type >, imf::Id, imf::Id, reference > type; + }; + /** * Constructor for a storage-based vector that allocates storage. */ @@ -598,6 +603,33 @@ namespace alp { return target_t( source ); } + /** + * Create a matrix view over a vector. + * The resulting matrix is a column matrix of size M x 1, where M is vector length. + * The function guarantees the created view is non-overlapping with other + * existing views only when the check can be performed in constant time. + * + * @tparam target_view The type of the view to apply to the vector. + * Only supports value view::matrix. + * @tparam SourceVector The type of the source ALP vector + * + * @param[in] source The ALP Vector object over which the view is created. + * + */ + template< + enum view::Views target_view, + typename SourceVector, + std::enable_if_t< + is_vector< SourceVector >::value && + target_view == view::matrix + > * = nullptr + > + typename SourceVector::template view_type< target_view >::type + get_view( SourceVector &source ) { + using target_t = typename SourceVector::template view_type< target_view >::type; + return target_t( source ); + } + namespace internal { /** diff --git a/include/alp/storage.hpp b/include/alp/storage.hpp index 9acea1715..a3b6b5109 100644 --- a/include/alp/storage.hpp +++ b/include/alp/storage.hpp @@ -638,9 +638,7 @@ namespace alp { typedef AMF< final_imf_r_type, final_imf_c_type, final_polynomial_type > amf_type; - static - amf_type - Create( ViewImfR imf_r, ViewImfC imf_c, const AMF< SourceImfR, SourceImfC, SourcePoly > &amf ) { + static amf_type Create( ViewImfR imf_r, ViewImfC imf_c, const AMF< SourceImfR, SourceImfC, SourcePoly > &amf ) { composed_imf_r_type composed_imf_r { imf::ComposedFactory::create( amf.imf_r, imf_r ) }; composed_imf_c_type composed_imf_c { imf::ComposedFactory::create( amf.imf_c, imf_c ) }; return amf_type( @@ -746,9 +744,7 @@ namespace alp { typedef SourceAMF amf_type; - static - amf_type - Create( const SourceAMF &amf ) { + static amf_type Create( const SourceAMF &amf ) { throw std::invalid_argument( "Not implemented for the provided view type." ); return amf; } @@ -762,9 +758,7 @@ namespace alp { typedef SourceAMF amf_type; - static - amf_type - Create( const SourceAMF &amf ) { + static amf_type Create( const SourceAMF &amf ) { return amf_type( amf.imf_r, amf.imf_c, amf.map_poly, amf.storage_dimensions ); } @@ -784,9 +778,7 @@ namespace alp { >::type > amf_type; - static - amf_type - Create( const SourceAMF &amf ) { + static amf_type Create( const SourceAMF &amf ) { typedef typename polynomials::apply_view< view::transpose, typename SourceAMF::mapping_polynomial_type >::type new_mapping_polynomial_type; return AMF< typename SourceAMF::imf_c_type, @@ -839,9 +831,7 @@ namespace alp { typedef AMF< imf::Id, imf::Zero, new_poly_type > amf_type; - static - amf_type - Create( const SourceAMF &amf ) { + static amf_type Create( const SourceAMF &amf ) { assert( amf.getLogicalDimensions().first == amf.getLogicalDimensions().second ); return amf_type( imf::Id( amf.getLogicalDimensions().first ), @@ -859,6 +849,30 @@ namespace alp { }; // class Reshape< diagonal, ... > + /** + * Specialization for matrix views over vectors + * + * \note \internal The resulting AMF is equivalent to applying + * a composition with two ID IMFs. + * + */ + template< typename SourceAMF > + struct Reshape< view::matrix, SourceAMF > { + + typedef typename AMFFactory::Compose< imf::Id, imf::Id, SourceAMF >::amf_type amf_type; + + static amf_type Create( const SourceAMF &amf ) { + return storage::AMFFactory::Compose< imf::Id, imf::Id, SourceAMF >::Create( + imf::Id( amf.getLogicalDimensions().first ), + imf::Id( amf.getLogicalDimensions().second ), + amf + ); + } + + Reshape() = delete; + + }; // class Reshape< diagonal, ... > + }; // class AMFFactory }; // namespace storage diff --git a/include/alp/views.hpp b/include/alp/views.hpp index dad5ba99e..e5a3c954c 100644 --- a/include/alp/views.hpp +++ b/include/alp/views.hpp @@ -52,6 +52,7 @@ namespace alp { gather, transpose, diagonal, + matrix, _internal }; @@ -91,6 +92,15 @@ namespace alp { }; + template< typename OriginalType > + struct Matrix { + + using applied_to = OriginalType; + + static constexpr Views type_id = Views::matrix; + + }; + template< typename LambdaFunctionType > struct Functor { diff --git a/tests/unit/alp_views.cpp b/tests/unit/alp_views.cpp index d7ddce61b..453fbd110 100644 --- a/tests/unit/alp_views.cpp +++ b/tests/unit/alp_views.cpp @@ -189,6 +189,14 @@ void alpProgram( const size_t &n, alp::RC &rc ) { auto v_view = alp::get_view( v, alp::utils::range( 1, 3 ) ); print_vector( "v_view", v_view ); + // matrix view over an original vector + auto v_mat_view = alp::get_view< alp::view::matrix >( v ); + print_matrix( "v_mat_view", v_mat_view ); + + // matrix view over a vector, which is a vector view over a matrix + auto Mrow_mat_view = alp::get_view< alp::view::matrix >( Mrow ); + print_matrix( "Mrow_mat_view", Mrow_mat_view ); + rc = alp::SUCCESS; }