// -*- c++ -*- // // $COPYRIGHT$ // //=========================================================================== #ifndef _MTL_MATRIX_H_ #define _MTL_MATRIX_H_ /* namespace polution from */ #undef major #undef minor #include #include #include #include "mtl/meta_equal.h" #include "mtl/meta_if.h" #include "mtl/matrix_traits.h" #include "mtl/compressed1D.h" #include "mtl/matrix_implementation.h" #include "mtl/rect_indexer.h" #include "mtl/banded_indexer.h" #include "mtl/diagonal_indexer.h" #include "mtl/dense2D.h" #include "mtl/array2D.h" #include "mtl/compressed2D.h" #include "mtl/envelope2D.h" #include #include #include #include "mtl/linalg_vec.h" #include "mtl/sparse1D.h" #include "mtl/entry.h" #include "mtl/uplo.h" #include "mtl/selectors.h" namespace mtl { /* Shapes */ //: generators for oned //!noindex: template struct generate_oned { enum { Storage_oned_id = Storage::oned_id, Storage_index = Storage::index }; typedef typename IF< EQUAL< Storage_oned_id,DENSE>::RET, dense1D, typename IF< EQUAL< Storage_oned_id,COMPRESSED>::RET, compressed1D, typename IF< EQUAL< Storage_oned_id,SPARSE_PAIR>::RET, sparse1D< mtl::dense1D< entry1 > >, typename IF< EQUAL< Storage_oned_id,TREE>::RET, sparse1D< std::set< entry1 > >, typename IF< EQUAL< Storage_oned_id,LINKED_LIST>::RET, sparse1D< std::list< entry1 > >, generators_error >::RET >::RET >::RET >::RET >::RET RET; }; //: blah //!noindex: template struct generate_internal { enum { Storage_id = Storage::id, Storage_index = Storage::index }; typedef typename IF< EQUAL< Storage_id, DENSE>::RET, gen_dense2D,M,N>, typename IF< EQUAL< Storage_id, COMPRESSED >::RET, gen_compressed2D, typename IF< EQUAL< Storage_id, ENVELOPE >::RET, gen_envelope2D, typename IF< EQUAL< Storage_id, PACKED >::RET, gen_dense2D,M,N>, typename IF< EQUAL< Storage_id, BAND >::RET, gen_dense2D,M,N>, typename IF< EQUAL< Storage_id, BAND_VIEW >::RET, gen_dense2D,M,N>, typename IF< EQUAL< Storage_id, ARRAY >::RET, gen_array2D< typename generate_oned::RET >, generators_error >::RET >::RET >::RET >::RET >::RET >::RET >::RET RET; }; //: blah //!noindex: template struct generate_external { enum { Storage_id = Storage::id, Storage_index = Storage::index }; typedef typename IF< EQUAL< Storage_id, DENSE>::RET, gen_external2D, M,N>, typename IF< EQUAL< Storage_id, COMPRESSED >::RET, gen_ext_comp2D, typename IF< EQUAL< Storage_id, ENVELOPE >::RET, gen_envelope2D, typename IF< EQUAL< Storage_id, PACKED >::RET, gen_external2D,M,N>, typename IF< EQUAL< Storage_id, BAND >::RET, gen_external2D,M,N>, typename IF< EQUAL< Storage_id, BAND_VIEW >::RET, gen_external2D,M,N>, typename IF< EQUAL< Storage_id, ARRAY >::RET, gen_array2D< typename generate_oned::RET >, generators_error >::RET >::RET >::RET >::RET >::RET >::RET >::RET RET; }; //: blah //!noindex: template struct generate_storage { enum { Storage_ext = Storage::ext }; typedef typename IF< Storage_ext, typename generate_external::RET, typename generate_internal::RET >::RET RET; }; template class dense_matrix; template class external_dense_matrix; template class static_dense_matrix; //: blah //!noindex: template struct generate_rect { enum { Orientation_id = Orientation::id }; #if 0 typedef typename generate_storage::RET storage_t; typedef typename storage_t::type::size_type size_type; typedef typename IF< EQUAL::RET, row_matrix< storage_t, gen_rect_indexer >, typename IF< EQUAL::RET, column_matrix< storage_t, gen_rect_indexer >, generators_error >::RET >::RET RET; #else enum { Storage_id = Storage::id, Storage_issparse = Storage::issparse, Storage_ext = Storage::ext }; // typedef typename storage_t::type::size_type size_type; typedef int size_type; // JGS!! typedef typename IF< EQUAL::RET, typename IF< Storage_ext, external_dense_matrix, dense_matrix >::RET, typename IF< EQUAL::RET, typename IF< EQUAL::RET, row_matrix< typename generate_storage::RET, gen_rect_indexer >, typename IF< EQUAL::RET, column_matrix< typename generate_storage::RET, gen_rect_indexer >, generators_error >::RET >::RET, typename IF< Storage_issparse, typename IF< EQUAL::RET, row_matrix< typename generate_storage::RET, gen_rect_indexer >, typename IF< EQUAL::RET, column_matrix< typename generate_storage::RET, gen_rect_indexer >, generators_error >::RET >::RET, generators_error >::RET >::RET >::RET RET; #endif }; //: blah //!noindex: template struct generate_banded { enum { Orientation_id = Orientation::id }; enum { Storage_id = Storage::id, Storage_issparse = Storage::issparse, Storage_ext = Storage::ext }; typedef typename generate_storage::RET storage_t; typedef typename storage_t::type::size_type size_type; typedef typename IF< EQUAL::RET, typename IF, banded_matrix >::RET, typename IF< EQUAL::RET, row_matrix< storage_t, gen_banded_indexer >, typename IF< EQUAL::RET, column_matrix< storage_t, gen_banded_indexer >, generators_error >::RET >::RET >::RET RET; }; //: blah //!noindex: template struct generate_diagonal { typedef typename generate_storage::RET storage_type; typedef typename storage_type::type::size_type size_type; typedef gen_diagonal_indexer indexer_gen; typedef diagonal_matrix_old RET; }; //: blah //!noindex: template struct generate_uplo { typedef typename IF< EQUAL< Uplo, upper >::RET, upper__, typename IF< EQUAL< Uplo, unit_upper >::RET, unit_upper__, typename IF< EQUAL< Uplo, lower>::RET, lower__, typename IF< EQUAL< Uplo, unit_lower>::RET, unit_lower__, dynamic_uplo__ >::RET >::RET >::RET >::RET RET; }; //: blah //!noindex: template struct generate_triangle { enum { Orien_id = Orien::id, Shape_uplo = Shape::uplo, // Shape_diag = Shape::diag, Storage_id = Storage::id, Storage_issparse = Storage::issparse, Storage_isext = Storage::ext }; enum { UnitDiag = convert_diag<(uplo_e)Shape_uplo>::RET, newUplo = convert_uplo<(uplo_e)Shape_uplo>::RET }; typedef typename generate_storage::RET storage_type; typedef typename storage_type::type::size_type size_type; typedef typename IF< Storage_issparse, typename IF< EQUAL< Orien_id, ROW_MAJOR>::RET, triangle_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET >, triangle_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET > >::RET , #if 0 typename IF< EQUAL< Orien_id, ROW_MAJOR>::RET, triangle_matrix >, typename generate_uplo<(uplo_e)Shape_uplo>::RET >, triangle_matrix >, typename generate_uplo<(uplo_e)Shape_uplo>::RET > >::RET typename IF< EQUAL< Orien_id, ROW_MAJOR>::RET, triangle_matrix >, typename generate_uplo<(uplo_e)Shape_uplo>::RET >, triangle_matrix >, typename generate_uplo<(uplo_e)Shape_uplo>::RET > >::RET #else // packed typename IF< EQUAL< Storage_id, PACKED>::RET, typename IF< Storage_isext, external_triangle_packed_matrix, triangle_packed_matrix >::RET, // banded typename IF< EQUAL< Storage_id, BAND>::RET, typename IF< Storage_isext, external_triangle_banded_matrix, triangle_banded_matrix >::RET, // regular typename IF< EQUAL< Storage_id, BAND_VIEW>::RET, typename IF< Storage_isext, external_triangle_matrix, triangle_matrix >::RET, // old school typename IF< EQUAL< Orien_id, ROW_MAJOR>::RET, triangle_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET >, triangle_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET > >::RET >::RET >::RET >::RET #endif >::RET RET; }; /* if storage is sparse, use rect indexer, otherwise use banded indexer */ //: blah //!noindex: template struct generate_symmetric { enum { Shape_uplo = Shape::uplo, Orien_id = Orien::id, Storage_isext = Storage::ext, Storage_id = Storage::id, Storage_issparse = Storage::issparse }; enum { newUplo = convert_uplo<(uplo_e)Shape_uplo>::RET }; typedef typename generate_storage::RET storage_type; typedef typename storage_type::type::size_type size_type; typedef typename IF< Storage_issparse, typename IF< EQUAL< Orien_id, ROW_MAJOR>::RET, symmetric_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET, IsHerm >, symmetric_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET, IsHerm > >::RET , #if 0 typename IF< EQUAL< Orien_id, ROW_MAJOR>::RET, symmetric_matrix >, typename generate_uplo<(uplo_e)Shape_uplo>::RET, IsHerm >, symmetric_matrix >, typename generate_uplo<(uplo_e)Shape_uplo>::RET, IsHerm > >::RET #else // packed typename IF< EQUAL< Storage_id, PACKED>::RET, typename IF< Storage_isext, external_symmetric_packed_matrix, symmetric_packed_matrix >::RET, // banded typename IF< EQUAL< Storage_id, BAND>::RET, typename IF< Storage_isext, external_symmetric_banded_matrix, symmetric_banded_matrix >::RET, // regular typename IF< EQUAL< Storage_id, BAND_VIEW>::RET, typename IF< Storage_isext, external_symmetric_matrix, symmetric_matrix >::RET, // old school typename IF< EQUAL< Orien_id, ROW_MAJOR>::RET, symmetric_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET, IsHerm >, symmetric_matrix_old >, typename generate_uplo<(uplo_e)Shape_uplo>::RET, IsHerm > >::RET >::RET >::RET >::RET #endif >::RET RET; }; //: Matrix type generators class. // // Matrices that occur in real engineering and scientific applications // often have special structure, especially in terms of how many zeros // are in the matrix, and where the non-zeros are located in the matrix. // This means that space and time saving can be acheived by using various // types of compressed storage. There are a multitude of matrix storage // formats in use today, and the MTL tries to support many of the more // common storage formats. The following discussion will describe how the // user of MTL can select the type of matrix he or she wishes to use. // // To create a MTL matrix, one first needs to construct the // appropriate matrix type. This is done using the matrix // type generation class, which is easier to think of as a function. It // takes as input the characteristics of the matrix type that you want // and then returns the appropriate MTL matrix. The matrix type // generators ``function'' has defaults defined, so in order to create a // normal rectangular matrix type, one merely does the following: // // // typedef matrix< double >::type MyMatrix; // MyMatrix A(M, N); // // // The matrix type generators can take up to four arguments, the // element type, the matrix shape, the storage // format, and the orientation. The following is the // ``prototype'' for the matrix type generators. // // // matrix< EltType, Shape, Storage, Orientation >::type // // // This type of "generative" interface technique was developed by by // Krzysztof // Czarnecki and Ulrich // Eisenecker in their work on the Generative Matrix Computation Library. //

// *Storage can be made external by specifying such in the storage // parameter. eg. dense<external>, packed<external>. // //!tparam: EltType - Valid choices for this argument include double, complex, and bool. In essence, any builtin or user defined type can be used for the EltType, however, if one uses the matrix with a particular algorithm, the EltType must support the operations required by the algorithm. For MTL algorithms these typically include the usual numerical operators such as addition and multiplication. The std::complex class is a good example of what is required in a numerical type. The documentation for each algorithm will include the requirements on the element type. // //!tparam: Shape - This argument specifies the general positioning of the non zero elements in the matrix, but does not specify the actual storage format. In addition it specifies certain properties such as symmetry. The choices for this argument include rectangle, banded, diagonal, triangle, and symmetric. Hermitian is not yet implemented. // //!tparam: Storage - The argument specifies the storage scheme used to lay out the matrix elements (and sometimes the element indices) in memory. The storage formats include dense , banded, packed , banded_view, compressed, envelope, and array. // //!tparam: Orientation - The storage order for an MTL matrix can either be row_major or column_major. // //!category: containers, generators //!component: type //!definition: matrix.h // template < class T, class Shape = rectangle<>, class Storage = dense<>, class Orientation = row_major > struct matrix { enum { Shape_id = Shape::id, Shape_M = Shape::M, Shape_N = Shape::N }; //: The generated type typedef typename IF< EQUAL< Shape_id, RECT>::RET, typename generate_rect::RET, typename IF< EQUAL< Shape_id, DIAG>::RET, typename generate_diagonal::RET, typename IF< EQUAL< Shape_id, BAND>::RET, typename generate_banded::RET, typename IF< EQUAL< Shape_id, TRI>::RET, typename generate_triangle::RET, typename IF< EQUAL< Shape_id, SYMM>::RET, typename generate_symmetric::RET, typename IF< EQUAL< Shape_id, HERM>::RET, typename generate_symmetric::RET, generators_error >::RET >::RET >::RET >::RET >::RET >::RET type; }; #ifndef MTL_DISABLE_BLOCKING //: Block View Matrix Type Constructor // // // block_view bA = blocked<>(A, 16, 16); // or // block_view bA = blocked(A); // // // Note: currently not supported for egcs (internal compiler error). // //!category: containers, generators //!component: type //!example: blocked_matrix.cc //!definition: matrix.h //!tparam: Matrix - The type of the Matrix to be blocked, must be dense //!tparam: BM - The blocking factor for the rows (M dimension) - 0 for dynamic size //!tparam: BN - The blocking factor for the columns (N dimension) - 0 for dynamic size template struct block_view { //: The generated type typedef typename Matrix:: MTL_TEMPLATE blocked_view::type type; }; template struct blk { enum { M = BM, N = BN }; }; //: Blocked Matrix Generator // // // block_view bA = blocked<>(A, 16, 16); // // // Note: currently not supported for egcs (internal compiler error). // //!category: containers //!component: function //!example: blocked_matrix.cc //!definition: matrix.h //!tparam: Matrix - The type of the Matrix to be blocked, must be dense template typename block_view::type blocked(const Matrix& A, int bm, int bn) { typedef dimension bdt; return typename block_view::type(A, bdt(bm, bn)); } //: Blocked Matrix Generator // // This version of the blocked matrix generator is for statically // sized blocks. // // // block_view bA = blocked(A); // // // Note: currently not supported for egcs (internal compiler error). // //!category: containers //!component: function //!example: blocked_matrix.cc //!definition: matrix.h //!tparam: Matrix - The type of the Matrix to be blocked, must be dense //!tparam: BM - The blocking factor for the rows (M dimension) //!tparam: BN - The blocking factor for the columns (N dimension) template typename block_view::type blocked(const Matrix& A, blk) { typedef dimension bdt; return typename block_view::type(A, bdt(BM, BN)); } #endif //: Band View Matrix Type Constructor // A helper class for creating a banded_view into an existing dense matrix. //!category: containers, generators //!component: type //!example: banded_view_test.cc //!definition: matrix.h //!tparam: Matrix - The type of the Matrix to be viewed, must be dense template struct band_view { //: The generated type typedef typename Matrix::banded_view_type type; }; //: Triangle View Matrix Type Constructor // A helper class for creating a triangle view into an existing dense // or sparse matrix. For sparse matrices, the matrix must already // have elements in the appropriate triangular portion of the matrix. // This just provides the proper triangular matrix interface. //!category: containers, generators //!component: type //!example: banded_view_test.cc //!definition: matrix.h //!tparam: Matrix - The type of the Matrix to be viewed, must be dense //!tparam: Uplo - Whether to view the upper or lower triangle of the matrix template struct triangle_view { typedef typename Matrix::sparsity Sparsity; enum { Sparsity_id = Sparsity::id }; //: The generated type typedef typename IF< EQUAL< Sparsity_id, DENSE>::RET, triangle_matrix_old< typename Matrix::banded_view_type, typename generate_uplo::RET>, triangle_matrix_old< Matrix, typename generate_uplo::RET> >::RET type; }; //: Triangle View Creation Helper Fuctor // Example: tri_view()(A) //!category: containers, generators //!component: type //!example: banded_view_test.cc //!definition: matrix.h //!tparam: Uplo - Whether to view the upper or lower triangle of the matrix template struct tri_view { template inline typename triangle_view::type operator()(Matrix x) { typedef typename triangle_view::type TriView; return TriView(x); } }; //: Symmetric View Matrix Type Constructor // A helper class for creating a symmetric view into an existing dense // or sparse matrix. For sparse matrices, the matrix must already // have elements in the appropriate lower/upper portion of the matrix. // This just provides the proper symmetric matrix interface. //!category: containers, generators //!component: type //!definition: matrix.h //!tparam: Matrix - The type of the Matrix to be viewed, must be dense //!tparam: Uplo - Whether to view the upper or lower triangle of the matrix template struct symmetric_view { typedef typename Matrix::sparsity Sparsity; enum { Sparsity_id = Sparsity::id }; //: The generated type typedef typename IF< EQUAL< Sparsity_id, DENSE>::RET, symmetric_matrix_old< typename Matrix::banded_view_type, typename generate_uplo::RET, 0>, symmetric_matrix_old< Matrix, typename generate_uplo::RET,0> >::RET type; }; } /* namespace mtl */ #endif /* _MTL_MATRIX_H_ */