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 &copy( 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 &copy( 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