1 /* 2 * Copyright (C) 2004 Pascal Giorgi, Clément Pernet 3 * 2013, 2014 the LinBox group 4 * 5 * Written by : 6 * Pascal Giorgi pascal.giorgi@ens-lyon.fr 7 * Clément Pernet clement.pernet@imag.fr 8 * Brice Boyer (briceboyer) <boyer.brice@gmail.com> 9 * 10 * ========LICENCE======== 11 * This file is part of the library LinBox. 12 * 13 * LinBox is free software: you can redistribute it and/or modify 14 * it under the terms of the GNU Lesser General Public 15 * License as published by the Free Software Foundation; either 16 * version 2.1 of the License, or (at your option) any later version. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * Lesser General Public License for more details. 22 * 23 * You should have received a copy of the GNU Lesser General Public 24 * License along with this library; if not, write to the Free Software 25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 * ========LICENCE======== 27 */ 28 29 /*! @file matrix/densematrix/blas-matrix.h 30 * @ingroup densematrix 31 * A \c BlasMatrix<\c _Field > represents a matrix as an array of 32 * <code>_Field::Element</code>s. It also has the BlasBlackbox interface. 33 * 34 */ 35 36 #ifndef __LINBOX_matrix_densematrix_blas_matrix_H 37 #define __LINBOX_matrix_densematrix_blas_matrix_H 38 39 #include <linbox/linbox-config.h> 40 #include "linbox/util/debug.h" 41 #include "linbox/linbox-tags.h" 42 #include "linbox/vector/stream.h" 43 #include "linbox/field/hom.h" 44 #include "linbox/vector/blas-vector.h" 45 46 #include "linbox/matrix/matrix-category.h" 47 #include "linbox/matrix/matrix-traits.h" 48 #include "linbox/util/matrix-stream.h" 49 50 #include "linbox/ring/modular.h" // just for checkBlasApply 51 #include <givaro/modular-balanced.h> // just for checkBlasApply 52 #include "givaro/zring.h" 53 //! @bug this does not belong here. 54 #include "blas-transposed-matrix.h" 55 #include "linbox/matrix/matrixdomain/matrix-domain.h" 56 #include "linbox/matrix/matrixdomain/apply-domain.h" 57 58 #include <givaro/modular.h> 59 60 namespace LinBox 61 { /* not generic wrt Field (eg NTL_ZZ_p) */ 62 namespace Protected 63 { 64 65 //!@bug this does not seem right for float or any non M/modular field: doing blas wherever we have a fflas-ffpack field (?) 66 //! @bug should return true for some Givaro::ZRing 67 template <class Field> checkBlasApply(const Field & F,size_t n)68 bool checkBlasApply(const Field &F, size_t n) 69 { 70 71 return false; 72 // integer chara, card; 73 // F.characteristic(chara); 74 // F.cardinality(card); 75 76 // if ((chara != card) || chara == 0) 77 // return false; 78 // else 79 // if (n*chara*chara < integer("9007199254740992")) 80 // return true; 81 // else 82 // return false; 83 } 84 85 template<> checkBlasApply(const Givaro::Modular<double> &,size_t)86 bool checkBlasApply(const Givaro::Modular<double> &, size_t) 87 { 88 return true; 89 } 90 91 template<> checkBlasApply(const Givaro::ModularBalanced<double> &,size_t)92 bool checkBlasApply(const Givaro::ModularBalanced<double> &, size_t) 93 { 94 return true; 95 } 96 97 template<> checkBlasApply(const Givaro::Modular<float> &,size_t)98 bool checkBlasApply(const Givaro::Modular<float> &, size_t) 99 { 100 return true; 101 } 102 103 template<> checkBlasApply(const Givaro::ModularBalanced<float> &,size_t)104 bool checkBlasApply(const Givaro::ModularBalanced<float> &, size_t) 105 { 106 return true; 107 } 108 109 template<> checkBlasApply(const Givaro::Modular<int64_t> &,size_t)110 bool checkBlasApply(const Givaro::Modular<int64_t> &, size_t) 111 { 112 return true; 113 } 114 115 template<> checkBlasApply(const Givaro::ModularBalanced<int64_t> &,size_t)116 bool checkBlasApply(const Givaro::ModularBalanced<int64_t> &, size_t) 117 { 118 return true; 119 } 120 121 template<> checkBlasApply(const Givaro::Modular<int32_t> &,size_t)122 bool checkBlasApply(const Givaro::Modular<int32_t> &, size_t) 123 { 124 return true; 125 } 126 127 template<> checkBlasApply(const Givaro::ModularBalanced<int32_t> &,size_t)128 bool checkBlasApply(const Givaro::ModularBalanced<int32_t> &, size_t) 129 { 130 return true; 131 } 132 template<> checkBlasApply(const Givaro::Modular<int16_t> &,size_t)133 bool checkBlasApply(const Givaro::Modular<int16_t> &, size_t) 134 { 135 return true; 136 } 137 138 template<> checkBlasApply(const Givaro::ModularBalanced<int16_t> &,size_t)139 bool checkBlasApply(const Givaro::ModularBalanced<int16_t> &, size_t) 140 { 141 return true; 142 } 143 144 } 145 } 146 147 namespace LinBox 148 { /* Blas Matrix */ 149 template<class Matrix> 150 class MatrixDomain; 151 152 /*! Dense matrix representation. 153 * @ingroup matrix 154 * A \p BlasMatrix is a matrix of \p _Field::Element, with the structure of BLAS matrices. 155 * It is basically a vector of \p _Field::Element. 156 * In the Mother model, a \p BlasMatrix is allocated by the user. 157 *@bug why not BlasMatrixDomain ? 158 */ 159 template <class _Field, class _Storage> 160 class BlasMatrix { 161 // private : 162 163 public: 164 typedef _Field Field; 165 typedef typename Field::Element Element; //!< Element type 166 typedef _Storage Rep; //!< Actually a <code>std::vector<Element></code> (or alike: cstor(n), cstor(n, val), operator[], resize(n).) 167 typedef typename Rep::pointer pointer; //!< pointer type to elements 168 typedef const pointer const_pointer; //!< const pointer type 169 typedef BlasMatrix<Field,Rep> Self_t; //!< Self typeype 170 typedef const BlasMatrix<Field,Rep> constSelf_t; //!< Self typeype 171 172 typedef BlasSubmatrix<Self_t> subMatrixType; //!< Submatrix type 173 typedef BlasSubmatrix<constSelf_t> constSubMatrixType; //!< Submatrix type 174 typedef Self_t matrixType; //!< matrix type 175 typedef constSelf_t constMatrixType; //!< matrix type 176 typedef Self_t blasType; //!< blas matrix type 177 178 protected: 179 size_t _row; 180 size_t _col; 181 Rep _rep; 182 public: 183 bool _use_fflas ; //! @bug why public ? 184 //protected: 185 pointer _ptr; 186 public: 187 // protected: 188 const Field * _field; //! @bug why public ? 189 MatrixDomain<Field> _MD; //! @bug why public ? 190 VectorDomain<Field> _VD; 191 // applyDomain<subMatrixType> _AD; //! @bug why public ? 192 // applyDomain<Self_t> _AD; //! @bug why public ? 193 194 195 private: 196 197 #if 0 198 void makePointer() 199 { 200 #if 0 201 if (_row && _col) { 202 _ptr = malloc( _row*_col*sizeof(_Element) ) ; 203 linbox_check(_ptr); 204 } 205 else 206 _ptr = NULL ; 207 #endif 208 _rep = Rep(_row*_col); 209 _ptr = _rep.data(); 210 } 211 #endif 212 213 /*! @internal 214 * @name create BlasMatrix 215 * @{ */ 216 217 /*! @internal 218 * Copy data according to blas container structure. 219 * Specialisation for BlasContainer. 220 */ 221 void createBlasMatrix (const Self_t & A) ; 222 223 /*! @internal 224 * Copy data according to blas container structure. 225 * Specialisation for BlasContainer. 226 */ 227 template <class _Matrix> 228 void createBlasMatrix (const _Matrix& A, MatrixContainerCategory::BlasContainer) ; 229 230 /*! @internal 231 * Copy data according to Matrix container structure. 232 * Specialisation for Container 233 */ 234 template <class Matrix> 235 void createBlasMatrix (const Matrix& A, MatrixContainerCategory::Container) ; 236 237 /*! @internal 238 * Copy data according to blackbox structure. 239 * Specialisation for Blackbox. 240 */ 241 template <class Matrix> 242 void createBlasMatrix (const Matrix& A, MatrixContainerCategory::Blackbox) ; 243 244 /*! @internal 245 * Copy data according to Matrix container structure (allow submatrix). 246 * Specialisation for Container 247 */ 248 template <class _Matrix> 249 void createBlasMatrix (const _Matrix& A, 250 const size_t i0,const size_t j0, 251 const size_t m, const size_t n, 252 MatrixContainerCategory::Container) ; 253 254 /*! @internal 255 * Copy data according to Matrix container structure (allow submatrix). 256 * Specialisation for BlasContainer. 257 */ 258 template <class Matrix> 259 void createBlasMatrix (const Matrix& A, 260 const size_t i0,const size_t j0, 261 const size_t m, const size_t n, 262 MatrixContainerCategory::BlasContainer) ; 263 264 /*! @internal 265 * Copy data according to blackbox structure (allow submatrix). 266 * Specialisation for Blackbox matrices 267 * @todo need to be implemented by succesive apply 268 */ 269 template <class Matrix> 270 void createBlasMatrix (const Matrix& A, 271 const size_t i0,const size_t j0, 272 const size_t m, const size_t n, 273 MatrixContainerCategory::Blackbox) ; 274 275 /*!@internal constructor from vector of elements. 276 * @param v pointer to \c Element s 277 */ 278 void createBlasMatrix ( const Element * v) ; 279 280 /*!@internal constructor from vector of elements. 281 * @param v std::vector of \c Element s 282 */ 283 void createBlasMatrix ( const std::vector<Element> & v) ; 284 /*! @internal 285 * @} 286 */ 287 288 public: 289 290 ////////////////// 291 // CONSTRUCTORS // 292 ////////////////// 293 294 295 /*! Allocates a new \f$ 0 \times 0\f$ matrix (shaped and ready). 296 */ 297 BlasMatrix (const _Field &F) ; 298 299 // /*! Allocates a new bare \f$ 0 \times 0\f$ matrix (unshaped, unready). 300 // */ 301 // BlasMatrix () ; 302 303 /// (Re)allocates a new \f$ m \times n\f$ zero matrix (shaped and ready). 304 void init(const _Field & F, const size_t & r = 0, const size_t & c = 0); 305 306 /*! Allocates a new \f$ m \times n\f$ zero matrix (shaped and ready). 307 * @param F 308 * @param m rows 309 * @param n cols 310 */ 311 //@{ 312 313 BlasMatrix (const _Field &F, const size_t & m, const size_t &n) ; 314 315 //@} 316 317 318 /*! Constructor from a matrix stream. 319 * @param ms matrix stream. 320 */ 321 BlasMatrix(MatrixStream<_Field>& ms) ; 322 323 /*! Generic copy constructor from either a blackbox or a matrix container. 324 * @param A matrix to be copied 325 */ 326 template <class Matrix> 327 BlasMatrix (const Matrix &A) ; 328 329 /*! Generic copy constructor from either a blackbox or a matrix container (allow submatrix). 330 * @param A matrix to be copied 331 * @param i0 332 * @param j0 333 * @param m rows 334 * @param n columns 335 */ 336 template <class Matrix> 337 BlasMatrix (const Matrix& A, 338 const size_t & i0, const size_t & j0, 339 const size_t & m, const size_t & n) ; 340 341 /*! Constructor. 342 * @param A matrix to be copied 343 * @param F Field 344 */ 345 template<class _Matrix> 346 BlasMatrix (const _Matrix &A, const _Field &F) ; 347 348 /*! Copy Constructor of a matrix (copying data). 349 * @param A matrix to be copied. 350 */ 351 BlasMatrix (const Self_t & A) ; 352 353 /*- Copy Constructor of a matrix (copying data). 354 * @param A matrix to be copied. 355 */ 356 // BlasMatrix (const BlasSubmatrix<Field,Rep>& A) ; 357 358 /*! Create a BlasMatrix from a vector of elements 359 * @param F 360 * @param v 361 * @param m 362 * @param n 363 */ 364 BlasMatrix (const _Field &F, const std::vector<Element>& v, 365 const size_t &m , const size_t &n) ; 366 367 /*! Create a BlasMatrix from an array of elements 368 * @param F 369 * @param v 370 * @param m 371 * @param n 372 */ 373 BlasMatrix (const _Field &F, const Element * v, 374 const size_t & m, const size_t & n) ; 375 376 377 /** Constructor using a finite vector stream (stream of the rows). 378 * @param F The field of entries; passed so that arithmetic may be done 379 * on elements 380 * @param stream A vector stream to use as a source of vectors for this 381 * matrix 382 */ 383 template <class StreamVector> 384 BlasMatrix (const Field &F, VectorStream<StreamVector> &stream) ; 385 386 /// Destructor. 387 ~BlasMatrix () ; 388 389 //! operator = (copying data) 390 Self_t& operator= (const Self_t& A) ; 391 392 /// Make this a (deep)copy of B. Assumes same shape. 393 //! make sure we actually copy 394 template<class Matrix> copy(const Matrix & B)395 BlasMatrix ©( const Matrix & B) 396 { 397 Element x; field().init(x); 398 for (size_t i = 0 ; i < rowdim() ; ++i) 399 for (size_t j = 0 ; j < coldim() ; ++j) { 400 setEntry(i,j,B.getEntry(x,i,j)); 401 } 402 return *this; 403 404 } 405 406 407 //! Rebind operator 408 template<typename _Tp1> 409 struct rebind ; 410 411 ////////////////// 412 // DIMENSIONS // 413 ////////////////// 414 415 /** Get the number of rows in the matrix. 416 * @returns Number of rows in matrix 417 */ 418 size_t rowdim() const ; 419 420 /** Get the number of columns in the matrix. 421 * @returns Number of columns in matrix 422 */ 423 size_t coldim() const ; 424 425 /*! Get the stride of the matrix. 426 */ 427 size_t getStride() const; stride()428 size_t stride() const { return getStride() ;} 429 430 /*!Get a reference to the stride of the matrix. 431 * Modify stride this way. 432 */ 433 size_t& getWriteStride(); 434 435 436 /** Resize the matrix to the given dimensions. 437 * The state of the matrix's entries after a call to this method is 438 * undefined 439 * @param m Number of rows 440 * @param n Number of columns 441 * @param val 442 */ 443 void resize (const size_t &m, const size_t &n, const Element& val = Element()) ; 444 445 ////////////////// 446 // ELEMENTS // 447 ////////////////// 448 449 /*! @internal 450 * Get read-only pointer to the matrix data. 451 */ 452 pointer getPointer() ; 453 const_pointer getPointer() const ; 454 const_pointer getConstPointer() const ; 455 refRep()456 Rep & refRep() { return _rep ;} getRep()457 const Rep & getRep() const { return _rep ;} 458 459 460 /*! @internal 461 * Get write pointer to the matrix data. 462 * Data may be changed this way. 463 */ 464 pointer& getWritePointer() ; 465 466 /** Set the entry at the (i, j) position to a_ij. 467 * @param i Row number, 0...rowdim () - 1 468 * @param j Column number 0...coldim () - 1 469 * @param a_ij Element to set 470 */ 471 const Element& setEntry (size_t i, size_t j, const Element &a_ij) ; 472 473 /** Get a writeable reference to the entry in the (i, j) position. 474 * @param i Row index of entry 475 * @param j Column index of entry 476 * @returns Reference to matrix entry 477 */ 478 Element &refEntry (size_t i, size_t j) ; 479 480 /** Get a read-only reference to the entry in the (i, j) position. 481 * @param i Row index 482 * @param j Column index 483 * @returns Const reference to matrix entry 484 */ 485 const Element &getEntry (size_t i, size_t j) const ; 486 487 /** Copy the (i, j) entry into x, and return a reference to x. 488 * This form is more in the Linbox style and is provided for interface 489 * compatibility with other parts of the library 490 * @param x Element in which to store result 491 * @param i Row index 492 * @param j Column index 493 * @returns Reference to x 494 */ 495 Element &getEntry (Element &x, size_t i, size_t j) const ; 496 497 /////////////////// 498 // TRANSPOSE &AL // 499 /////////////////// 500 501 /*! Creates a transposed matrix of \c *this. 502 * @param[in] tM 503 * @return the transposed matrix of this. 504 */ 505 Self_t transpose(Self_t & tM) const ; 506 507 508 /*! Transpose (inplace). 509 * If rows and columns agree, we can transpose inplace. 510 */ 511 template<bool _IP> 512 void transpose() ; 513 514 void transpose() ; 515 516 /*! Reverse the rows of a matrix. 517 * This is done inplace. 518 * Let J=antiDiag(1) (or the matrix of the reverse 519 * permutation or the matrix (i,j) = (i+j+1==m)). Then, 520 * we compute A <- J.A; 521 */ 522 void reverseRows() ; 523 524 /*! Reverse the columns of a matrix. 525 * This is done inplace. 526 * This is A <- J.A 527 */ 528 void reverseCols() ; 529 530 /*! Reverse the rows/columns of a matrix. 531 * This is done inplace. 532 * This is A <- J.A.J 533 */ 534 void reverse() ; 535 536 // init to field zero elements 537 void zero() ; 538 // init to random field elements random()539 void random() 540 { 541 subMatrixType B(*this, 0, 0, rowdim(), coldim()); 542 B.random(); 543 } 544 545 template<class Rand> random(const Rand &)546 void random(const Rand&) 547 { 548 return random(); 549 } 550 551 /////////////////// 552 // I/O // 553 /////////////////// 554 555 /** Read the matrix from an input stream. 556 * The stream is in SMS, DENSE, or MatrixMarket format and is autodetected. 557 * @param file Input stream from which to read 558 */ 559 std::istream &read (std::istream &file); 560 561 /// Write the matrix in MatrixMarket format. write(std::ostream & os)562 std::ostream &write (std::ostream &os) const 563 { 564 // std::cout << "writing" << std::endl; 565 constSubMatrixType B(*this, 0, 0, rowdim(), coldim()); 566 // std::cout << "......." << std::endl; 567 return B.write(os); 568 } 569 570 /** Write the matrix to an output stream. 571 * @param os Output stream to which to write 572 * @param f write in some format (@ref Tag::FileFormat::Format). Default is Maple's. 573 */ write(std::ostream & os,Tag::FileFormat f)574 std::ostream &write (std::ostream &os, 575 Tag::FileFormat f/* = Tag::FileFormat::Maple*/) const 576 { 577 constSubMatrixType B(*this, 0, 0, rowdim(), coldim()); 578 return B.write(os, f); 579 } 580 581 /*! @deprecated Only for compatiblity. 582 */ write(std::ostream & os,bool mapleFormat)583 std::ostream &write (std::ostream &os, 584 bool mapleFormat) const 585 { 586 constSubMatrixType B(*this, 0, 0, rowdim(), coldim()); 587 return B.write(os, mapleFormat); 588 } 589 590 591 592 593 /////////////////// 594 // ITERATORS // 595 /////////////////// 596 597 /** @name Column of rows iterator 598 * \brief 599 * The column of rows iterator traverses the rows of the 600 * matrix in ascending order. Dereferencing the iterator yields 601 * a row vector in dense format 602 */ 603 //@{ 604 typedef Subvector<typename Rep::iterator, typename Rep::const_iterator> Row; 605 typedef Subvector<typename Rep::const_iterator> ConstRow; 606 607 /*! Row Iterator. 608 * @ingroup iterators 609 * @brief NO DOC 610 */ 611 class RowIterator; 612 /*! Const Row Iterator. 613 * @ingroup iterators 614 * @brief NO DOC 615 */ 616 class ConstRowIterator; 617 618 RowIterator rowBegin (); 619 RowIterator rowEnd (); 620 ConstRowIterator rowBegin () const; 621 ConstRowIterator rowEnd () const; 622 //@} 623 624 /** @name Row of columns iterator 625 * \brief 626 * The row of columns iterator traverses the columns of the 627 * matrix in ascending order. Dereferencing the iterator yields 628 * a column vector in dense format 629 */ 630 //@{ 631 typedef Subvector<Subiterator<typename Rep::iterator> > Col; 632 typedef Subvector<Subiterator<typename Rep::const_iterator> > ConstCol; 633 typedef Col Column; 634 typedef ConstCol ConstColumn; 635 636 /*! Col Iterator. 637 * @ingroup iterators 638 * @brief NO DOC 639 */ 640 class ColIterator; 641 /*! Const Col Iterator. 642 * @ingroup iterators 643 * @brief NO DOC 644 */ 645 class ConstColIterator; 646 647 ColIterator colBegin (); 648 ColIterator colEnd (); 649 ConstColIterator colBegin () const; 650 ConstColIterator colEnd () const; 651 //@} 652 653 /** @name Iterator 654 * \brief 655 * 656 * The iterator is a method for accessing all entries in the matrix 657 * in some unspecified order. This can be used, e.g. to reduce all 658 * matrix entries modulo a prime before passing the matrix into an 659 * algorithm. 660 */ 661 //@{ 662 typedef typename Rep::iterator Iterator; 663 typedef typename Rep::const_iterator ConstIterator; 664 665 Iterator Begin (); 666 Iterator End (); 667 ConstIterator Begin () const; 668 ConstIterator End () const; 669 //@} 670 671 /** @name Raw Indexed iterator 672 * \brief 673 * 674 * Like the raw iterator, the indexed iterator is a method for 675 * accessing all entries in the matrix in some unspecified order. 676 * At each position of the the indexed iterator, it also provides 677 * the row and column indices of the currently referenced entry. 678 * This is provided through it's \c rowIndex() and \c colIndex() functions. 679 */ 680 //@{ 681 class IndexedIterator; 682 /*! Const Indexed Iterator. 683 * @ingroup iterators 684 * @brief NO DOC 685 */ 686 class ConstIndexedIterator; 687 688 IndexedIterator IndexedBegin (); 689 IndexedIterator IndexedEnd (); 690 ConstIndexedIterator IndexedBegin () const; 691 ConstIndexedIterator IndexedEnd () const; 692 //@} 693 694 /** Retrieve a reference to a row. 695 * Since rows may also be indexed, this allows A[i][j] notation 696 * to be used. 697 * @param i Row index 698 * @bug Rows and Cols should be BlasVectors 699 */ 700 //@{ 701 Row operator[] (size_t i) ; 702 ConstRow operator[] (size_t i) const ; 703 //@} 704 705 /////////////////// 706 // MISC // 707 /////////////////// 708 709 710 /** Compute column density. 711 * @param v 712 */ 713 template <class Vector> 714 Vector &columnDensity (Vector &v) const ; 715 size()716 size_t size() const 717 { 718 return _row * _col; 719 } 720 finalize()721 void finalize() {} 722 723 /////////////////// 724 // BLACK BOX // 725 /////////////////// 726 727 728 template <class Vector1, class Vector2> 729 Vector1& apply (Vector1& y, const Vector2& x) const ; 730 731 template<class _VRep> 732 BlasVector<Field,_VRep>& apply (BlasVector<Field,_VRep>& y, const BlasVector<Field,_VRep>& x) const ; 733 734 template <class Vector1, class Vector2> 735 Vector1& applyTranspose (Vector1& y, const Vector2& x) const ; 736 applyRight(subMatrixType & Y,const subMatrixType & X)737 subMatrixType& applyRight(subMatrixType& Y, const subMatrixType& X) 738 { return Y; } // temp applyLeft(subMatrixType & Y,const subMatrixType & X)739 subMatrixType& applyLeft(subMatrixType& Y, const subMatrixType& X) 740 { return Y; } // temp 741 742 const _Field& field() const; 743 //_Field& field() ; 744 // void setField(const _Field & F) { _field = F ; }; 745 746 template<class uselessTag> changeFieldSpecialised(_Field & G,VectorDomain<_Field> & VD,const _Field & F,const uselessTag & m)747 void changeFieldSpecialised( _Field & G, 748 // MatrixDomain<_Field> & MD, 749 VectorDomain<_Field> & VD, 750 const _Field & F, 751 const uselessTag & m) 752 { 753 // don't do anything (?) 754 return; 755 } 756 changeFieldSpecialised(_Field & G,VectorDomain<_Field> & VD,const _Field & F,const RingCategories::ModularTag & m)757 void changeFieldSpecialised( _Field & G, 758 // MatrixDomain<_Field> & MD, 759 VectorDomain<_Field> & VD, 760 const _Field & F, 761 const RingCategories::ModularTag & m) 762 { 763 G=F ; 764 // _MD = MatrixDomain<_Field>(F); 765 VD = VectorDomain<_Field>(F); 766 return; 767 } 768 769 changeField(const _Field & F)770 void changeField(const _Field &F) 771 { 772 changeFieldSpecialised(const_cast<_Field&>(_field), 773 // const_cast<MatrixDomain<_Field>&>(_MD), 774 const_cast<VectorDomain<_Field>&>(_VD), 775 F, 776 typename FieldTraits<_Field>::categoryTag()); 777 } 778 779 780 781 }; // end of class BlasMatrix 782 783 784 } // end of namespace LinBox 785 786 namespace LinBox 787 { /* Blas Submatrix */ 788 /*! Dense Submatrix representation. 789 * @ingroup matrix 790 * A @ref BlasSubmatrix is a matrix of \p _Field::Element, with the structure of BLAS matrices. 791 * It is basically a read/write view on a vector of \p _Field::Element. 792 * In the Mother model, a @ref BlasSubmatrix is not allocated. 793 * <p> 794 * This matrix type conforms to the same interface as @ref BlasMatrix, 795 * except that you cannot resize it. It represents a submatrix of a dense 796 * matrix. Upon construction, one can freely manipulate the entries in the 797 * DenseSubmatrix, and the corresponding entries in the underlying 798 * @ref BlasMatrix will be modified. 799 800 801 */ 802 template <class _Matrix> 803 class BlasSubmatrix { 804 public : 805 typedef typename _Matrix::Field Field; 806 typedef typename Field::Element Element; //!< Element type 807 typedef typename _Matrix::Rep Rep; 808 typedef BlasSubmatrix<_Matrix> Self_t; //!< Self type 809 typedef const BlasSubmatrix<typename _Matrix::constSelf_t> constSelf_t; //!< Self type (const) 810 811 typedef typename Rep::pointer pointer; //!< pointer type to elements 812 typedef const pointer const_pointer; //!< const pointer type 813 typedef Self_t subMatrixType; //!< Submatrix type 814 typedef constSelf_t constSubMatrixType; //!< Submatrix type (const) 815 typedef typename _Matrix::Self_t matrixType; //!< non const matrix type 816 typedef typename _Matrix::constSelf_t constMatrixType; //!< matrix type (const) 817 typedef matrixType blasType; //!< blas matrix type 818 typedef BlasVector<Field,Rep> vectorType; //!< blas matrix type 819 820 821 protected: 822 _Matrix &_Mat; //!< Parent BlasMatrix (ie encapsulated raw std::vector) 823 size_t _row; //!< row dimension of Submatrix 824 size_t _col; //!< col dimension of Submatrix 825 size_t _r0; //!< upper left corner row of Submatrix in \p _Mat 826 size_t _c0; //!< upper left corner row of Submatrix in \p _Mat 827 size_t _stride ; //!< number of columns in \p _Mat (or stride of \p _Mat) 828 size_t _off; //!< offset in \p _Mat, precomputed \c (_row*_stride+_col) 829 830 // applyDomain<matrixType> _AD; 831 applyDomain<constMatrixType> _AD; 832 public: 833 VectorDomain<Field> _VD; //!@bug NOT HERE 834 835 ////////////////// 836 // CONSTRUCTORS // 837 ////////////////// 838 839 840 /* constructors */ 841 842 // /** NULL constructor. */ 843 // BlasSubmatrix () ; 844 845 /** Constructor from an existing @ref BlasMatrix and dimensions. 846 * \param M Pointer to @ref BlasMatrix of which to construct submatrix 847 * \param rowbeg Starting row 848 * \param colbeg Starting column 849 * \param Rowdim Row dimension 850 * \param Coldim Column dimension 851 */ 852 BlasSubmatrix (constMatrixType &M, 853 size_t rowbeg, 854 size_t colbeg, 855 size_t Rowdim, 856 size_t Coldim); 857 858 BlasSubmatrix (matrixType &M, 859 size_t rowbeg, 860 size_t colbeg, 861 size_t Rowdim, 862 size_t Coldim); 863 864 865 866 /** Constructor from an existing @ref BlasMatrix 867 * \param M Pointer to @ref BlasMatrix of which to construct submatrix 868 */ 869 BlasSubmatrix (constMatrixType &M); 870 871 BlasSubmatrix (matrixType &M); 872 873 //! @todo BlasSub from (sub)Vector 874 // BlasSubmatrix (const vectorType &V); 875 876 877 /** Constructor from an existing submatrix and dimensions 878 * @param SM Constant reference to BlasSubmatrix from which to 879 * construct submatrix 880 * @param rowbeg Starting row 881 * @param colbeg Starting column 882 * @param Rowdim Row dimension 883 * @param Coldim Column dimension 884 */ 885 BlasSubmatrix (constSelf_t &SM, 886 size_t rowbeg, 887 size_t colbeg, 888 size_t Rowdim, 889 size_t Coldim); 890 891 BlasSubmatrix (Self_t &SM, 892 size_t rowbeg, 893 size_t colbeg, 894 size_t Rowdim, 895 size_t Coldim); 896 897 /** Copy constructor. 898 * @param SM Submatrix to copy 899 */ 900 BlasSubmatrix (constSelf_t &SM); 901 BlasSubmatrix (Self_t &SM); 902 903 904 /* Members */ 905 906 /** Assignment operator. 907 * Assign the given submatrix to this one 908 * This is <i>only</i> renaming ! 909 * There is no copy because BlasSubmatrix owns nothing. 910 * @param SM Submatrix to assign 911 * @return Reference to this submatrix 912 */ 913 BlasSubmatrix &operator = (const BlasSubmatrix<_Matrix> &SM); 914 915 // function for repurposing Submatrices. 916 BlasSubmatrix &submatrix(constSelf_t &SM, 917 size_t rowbeg, 918 size_t colbeg, 919 size_t Rowdim, 920 size_t Coldim); 921 922 /// This is deep copy of the data, operator= is a shallow copy. 923 template<class Matrix> 924 BlasSubmatrix ©( const Matrix & B); 925 926 /// Swap contents. Shapes must be the same. 927 BlasSubmatrix &swap( Self_t & B); 928 929 /// Overwrite with zeroes. 930 BlasSubmatrix &zero(); 931 932 /// Overwrite with random elements. 933 void random(); 934 935 template<class T> random(const T &)936 void random(const T&) 937 { 938 return random() ; 939 } 940 941 template<typename _Tp1, class _Rep2 = Rep> 942 struct rebind ; 943 944 ////////////////// 945 // DIMENSIONS // 946 ////////////////// 947 948 /** Get the number of rows in the matrix 949 * @return Number of rows in matrix 950 */ 951 size_t rowdim () const; 952 953 /** Get the number of columns in the matrix 954 * @return Number of columns in matrix 955 */ 956 size_t coldim () const ; 957 958 /*! Get the stride of the matrix. 959 * @return stride of submatrix (number of cols of dense base matrix) 960 */ 961 size_t getStride() const; stride()962 size_t stride() const { return getStride() ;} offset()963 size_t offset() const { return _off ; } 964 965 966 /////////////////// 967 // I/O // 968 /////////////////// 969 970 /** Read the matrix from an input stream. 971 * @param file Input stream from which to read 972 * @bug reading a submatrix should not be allowed !! 973 */ 974 // template<class Field> 975 std::istream& read (std::istream &file); // autodetect ? 976 977 978 /** Write the matrix to an output stream. 979 * @param os Output stream to which to write 980 * @param f write in some format (@ref Tag::FileFormat::Format). Default is MM's. 981 */ 982 std::ostream &write (std::ostream &os, 983 Tag::FileFormat f = Tag::FileFormat::MatrixMarket )const; 984 985 ////////////////// 986 // ELEMENTS // 987 ////////////////// 988 989 /*! @internal 990 * Get read-only pointer to the matrix data. 991 */ 992 pointer getPointer() ; 993 const_pointer getPointer() const ; 994 const_pointer getConstPointer() const ; 995 996 997 /*! @internal 998 * Get write pointer to the matrix data. 999 * Data may be changed this way. 1000 */ 1001 pointer/* & */ getWritePointer() ; 1002 1003 1004 /** Set the entry at (i, j). 1005 * @param i Row number, 0...rowdim () - 1 1006 * @param j Column number 0...coldim () - 1 1007 * @param a_ij Element to set 1008 */ 1009 const Element& setEntry (size_t i, size_t j, const Element &a_ij) ; 1010 1011 /** Get a writeable reference to an entry in the matrix. 1012 * @param i Row index of entry 1013 * @param j Column index of entry 1014 * @return Reference to matrix entry 1015 */ 1016 Element &refEntry (size_t i, size_t j) ; 1017 1018 /** Get a read-only individual entry from the matrix. 1019 * @param i Row index 1020 * @param j Column index 1021 * @return Const reference to matrix entry 1022 */ 1023 const Element &getEntry (size_t i, size_t j) const ; 1024 1025 /** Get an entry and store it in the given value. 1026 * This form is more in the Linbox style and is provided for interface 1027 * compatibility with other parts of the library 1028 * @param x Element in which to store result 1029 * @param i Row index 1030 * @param j Column index 1031 * @return Reference to x 1032 */ 1033 Element &getEntry (Element &x, size_t i, size_t j) const ; 1034 1035 1036 /////////////////// 1037 // ITERATORS // 1038 /////////////////// 1039 1040 //! @name Forward declaration of Raw Iterators. 1041 //@{ 1042 class Iterator ; 1043 class ConstIterator ; 1044 1045 class IndexedIterator ; 1046 class ConstIndexedIterator ; 1047 //@} 1048 1049 1050 /** @name typedef'd Row Iterators. 1051 *\brief 1052 * The row iterator gives the rows of the 1053 * matrix in ascending order. Dereferencing the iterator yields 1054 * a row vector in dense format 1055 * @{ 1056 */ 1057 typedef typename matrixType::RowIterator RowIterator; 1058 typedef typename matrixType::ConstRowIterator ConstRowIterator; 1059 typedef typename matrixType::Row Row; 1060 typedef typename matrixType::ConstRow ConstRow; 1061 //@} Row Iterators 1062 1063 /** @name typedef'd Column Iterators. 1064 *\brief 1065 * The columns iterator gives the columns of the 1066 * matrix in ascending order. Dereferencing the iterator yields 1067 * a column vector in dense format 1068 * @{ 1069 */ 1070 typedef typename matrixType::ColIterator ColIterator; 1071 typedef typename matrixType::ConstColIterator ConstColIterator; 1072 typedef typename matrixType::Col Col; 1073 typedef typename matrixType::Column Column; 1074 typedef typename matrixType::ConstCol ConstCol; 1075 //@} // Column Iterators 1076 1077 1078 1079 RowIterator rowBegin (); //!< iterator to the begining of a row 1080 RowIterator rowEnd (); //!< iterator to the end of a row 1081 ConstRowIterator rowBegin () const; //!< const iterator to the begining of a row 1082 ConstRowIterator rowEnd () const; //!< const iterator to the end of a row 1083 1084 ColIterator colBegin (); 1085 ColIterator colEnd (); 1086 ConstColIterator colBegin () const; 1087 ConstColIterator colEnd () const; 1088 1089 Iterator Begin (); 1090 Iterator End (); 1091 ConstIterator Begin () const; 1092 ConstIterator End () const; 1093 1094 1095 1096 IndexedIterator IndexedBegin(); 1097 IndexedIterator IndexedEnd(); 1098 ConstIndexedIterator IndexedBegin() const; 1099 ConstIndexedIterator IndexedEnd() const; 1100 1101 /*! operator[]. 1102 * Retrieve a reference to a row 1103 * @param i Row index 1104 */ 1105 Row operator[] (size_t i) ; 1106 ConstRow operator[] (size_t i) const ; 1107 1108 /////////////////// 1109 // BLACK BOX // 1110 /////////////////// 1111 1112 1113 //!@bug every vector we use here should have a stride/be blas vectors so it's not really templated by Vector1 Vector2 in general 1114 template <class Vector1, class Vector2> apply(Vector1 & y,const Vector2 & x)1115 Vector1& apply (Vector1& y, const Vector2& x) const 1116 { 1117 // std::cout << "prepare apply subMatrix" << std::endl; 1118 // constSelf_t A(*this); 1119 // std::cout << "........................" << std::endl; 1120 // _AD.apply(Tag::Transpose::NoTrans,y,field().one,A,field().zero,x); 1121 _AD.apply(Tag::Transpose::NoTrans,y,field().one,*this,field().zero,x); 1122 // std::cout << "........done............" << std::endl; 1123 return y; 1124 } 1125 1126 //! @bug use Matrix domain 1127 template <class Vector1, class Vector2> applyTranspose(Vector1 & y,const Vector2 & x)1128 Vector1& applyTranspose (Vector1& y, const Vector2& x) const 1129 { 1130 // std::cout << "prepare applyT subMatrix" << std::endl; 1131 // constSelf_t A(*this); 1132 // std::cout << "........................" << std::endl; 1133 // _AD.apply(Tag::Transpose::Trans,y,field().one,A,field().zero,x); 1134 _AD.apply(Tag::Transpose::Trans,y,field().one,*this,field().zero,x); 1135 // std::cout << "........done............" << std::endl; 1136 1137 return y; 1138 } 1139 field()1140 const Field& field() const { return _Mat.field() ;} 1141 // Field & field() { return _Mat.field(); } 1142 }; 1143 1144 } 1145 1146 namespace LinBox 1147 { /* Triangular Matrix */ 1148 //! Triangular BLAS matrix. 1149 template <class _Field, class _Storage > 1150 class TriangularBlasMatrix: public BlasMatrix<_Field,_Storage> { 1151 1152 protected: 1153 1154 Tag::Shape _uplo; //!< upper or lower triangular 1155 Tag::Diag _diag; //!< unit or non unit diagonal 1156 1157 public: 1158 typedef _Field Field; 1159 typedef _Storage Rep; 1160 typedef typename Field::Element Element; //!< Element type 1161 typedef BlasMatrix<Field,Rep> Father_t; 1162 typedef TriangularBlasMatrix<Field,Rep> Self_t; 1163 1164 1165 /*! Constructor for a new \c TriangularBlasMatrix. 1166 * @param F 1167 * @param m rows 1168 * @param n cols 1169 * @param y (non)unit diagonal 1170 * @param x (upp/low)er matrix 1171 */ 1172 TriangularBlasMatrix (const Field & F, 1173 const size_t m, const size_t n, 1174 Tag::Shape x=Tag::Shape::Upper, 1175 Tag::Diag y= Tag::Diag::NonUnit) ; 1176 1177 /*! Constructor from a \c BlasMatrix (copy). 1178 * @param A matrix 1179 * @param y (non)unit diagonal 1180 * @param x (upp/low)er matrix 1181 */ 1182 TriangularBlasMatrix (const BlasMatrix<Field,Rep>& A, 1183 Tag::Shape x=Tag::Shape::Upper, 1184 Tag::Diag y= Tag::Diag::NonUnit) ; 1185 1186 /*! Constructor from a \c BlasMatrix (no copy). 1187 * @param A matrix 1188 * @param y (non)unit diagonal 1189 * @param x (upp/low)er matrix 1190 */ 1191 TriangularBlasMatrix (BlasMatrix<Field,Rep>& A, 1192 Tag::Shape x=Tag::Shape::Upper, 1193 Tag::Diag y= Tag::Diag::NonUnit) ; 1194 1195 /*! Constructor from a \c TriangularBlasMatrix (copy). 1196 * @param A matrix 1197 */ 1198 TriangularBlasMatrix (const TriangularBlasMatrix<Field,Rep>& A) ; 1199 1200 /*! Generic constructor from a \c Matrix (no copy). 1201 * @param A matrix 1202 * @param y (non)unit diagonal 1203 * @param x (upp/low)er matrix 1204 */ 1205 template<class Matrix> 1206 TriangularBlasMatrix (const Matrix& A, 1207 Tag::Shape x=Tag::Shape::Upper, 1208 Tag::Diag y= Tag::Diag::NonUnit) ; 1209 1210 /// get the shape of the matrix (upper or lower) 1211 Tag::Shape getUpLo() const ; 1212 1213 /// Is the diagonal implicitly unit ? 1214 Tag::Diag getDiag() const ; 1215 1216 }; // end of class TriangularBlasMatrix 1217 1218 } // LinBox 1219 1220 #include <givaro/zring.h> 1221 1222 namespace LinBox 1223 { 1224 //! @bug does not work for submatrices. 1225 //! @todo b should be the random generator 1226 template<> 1227 template<> 1228 void BlasMatrix<Givaro::ZRing<Integer>, Vector<Givaro::ZRing<Integer>>::Dense >::random<size_t>(const size_t & b) 1229 { 1230 // std::cout << "randomized " << b << std::endl; 1231 typedef Givaro::ZRing<Integer> ZZ_t; 1232 ZZ_t::RandIter R(ZZ_t(), b); 1233 for (size_t i = 0 ; i < rowdim() ; ++i) 1234 for (size_t j = 0 ; j < coldim() ; ++j) 1235 R.random(refEntry(i,j)); 1236 1237 } 1238 1239 } // LinBox 1240 1241 #include "blas-matrix.inl" 1242 #include "blas-submatrix.inl" 1243 #include "blas-triangularmatrix.inl" 1244 1245 #endif // __LINBOX_densematrix_blas_matrix_H 1246 1247 // Local Variables: 1248 // mode: C++ 1249 // tab-width: 4 1250 // indent-tabs-mode: nil 1251 // c-basic-offset: 4 1252 // End: 1253 // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s 1254