1 /*
2  * Copyright (C) 2002 Zhendong Wan, Bradford Hovinen
3  * Copyright (C) 2013,2014 the LinBox group
4  *
5  * Written by Zhendong Wan <wan@mail.eecis.udel.edu>,
6  *            Bradford Hovinen <bghovinen@math.uwaterloo.ca>
7  *            Brice Boyer (briceboyer) <boyer.brice@gmail.com>
8  *
9  * ------------------------------------------------------------
10  * 2002-11-26  Bradford Hovinen  <bghovinen@math.uwaterloo.ca>
11  *
12  * Added detailed documentation, cleaned up the interface slightly, and added
13  * support for matrix traits. Added read, write, neg, negin, axpy, and
14  * matrix-vector and matrix-black box operations.
15  * ------------------------------------------------------------
16  *
17  *
18  * ========LICENCE========
19  * This file is part of the library LinBox.
20  *
21  * LinBox is free software: you can redistribute it and/or modify
22  * it under the terms of the  GNU Lesser General Public
23  * License as published by the Free Software Foundation; either
24  * version 2.1 of the License, or (at your option) any later version.
25  *
26  * This library is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29  * Lesser General Public License for more details.
30  *
31  * You should have received a copy of the GNU Lesser General Public
32  * License along with this library; if not, write to the Free Software
33  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
34  * ========LICENCE========
35  *.
36  */
37 
38 /** @file linbox/matrix/matrixdomain/matrix-domain.h
39  * @brief NO DOC
40  */
41 
42 #ifndef __LINBOX_matrixdomain_matrix_domain_H
43 #define __LINBOX_matrixdomain_matrix_domain_H
44 
45 #include <linbox/linbox-config.h>
46 #include <iostream>
47 #include <vector>
48 
49 #include "linbox/blackbox/archetype.h"
50 #include "linbox/matrix/matrix-traits.h"
51 // #include "linbox/vector/blas-vector.h"
52 
53 namespace LinBox
54 {
55 
56 
57 	/** Class of matrix arithmetic functions.
58 	 *
59 	 * This class encapuslated matrix-matrix and matrix-vector operations, roughly
60 	 * equivalent to BLAS levels 2 and 3. The arithmetic methods are parameterized
61 	 * by matrix type so that they may be used the same way with sparse matrices,
62 	 * dense matrices, and dense submatrices. Except where otherwise noted, they
63 	 * require the matrix inputs to meet the \ref BlasMatrix archetype.
64 	 *
65 	 * These methods are specialized so that they can run efficiently with different
66 	 * matrix representations. If a matrix has an efficient row iterator, but not an
67 	 * efficient column iterator, a specialization that makes use of the former will
68 	 * be selected. This allows a great deal of flexibility when dealing with sparse
69 	 * matrix arithmetic.
70 	 *
71 	 * For all of the arithmetic operations that output matrices, it is assumed that
72 	 * the output matrix has an efficient row iterator. In typical use, the output
73 	 * matrix will be a \ref BlasMatrix or a \ref BlasSubmatrix, which has
74 	 * efficient row and column iterators. In particular, one should not perform
75 	 * these arithmetic operations outputting to a \ref SparseMatrixBase.
76 	 *
77 	 * There are other restrictions. See the method-specific documentation for more
78 	 * details.
79 	 */
80 	template <class Field_ >
81 	class MatrixDomain : public MVProductDomain<Field_> {
82 	public:
83 		typedef size_t Index;
84 		typedef Field_ Field;
85 		typedef typename Field::Element Element;
86 		typedef Element Scalar;
87 		//! @bug should be BlasVector
88 		typedef typename Vector<Field>::Dense Rep_;
89 		// typedef Rep_ DenseVector;
90 		typedef BlasVector<Field_,Rep_> DenseVector;
91 		typedef BlasMatrix<Field,Rep_> OwnMatrix;
92 		typedef BlasSubmatrix<OwnMatrix> Matrix;
93 
94 		// MatrixDomain () {/*std::cerr << "MD def cstor" << std::endl;*/ }
95 
init(const Field & F)96 		void init(const Field & F) { _field = &F; _VD.init(F); }
97 
MatrixDomain()98 		MatrixDomain() {}
99 
100 		/// Constructor.
101 		//! @param F field for MatrixDomain operations.
MatrixDomain(const Field & F)102 		MatrixDomain (const Field &F) :
103 			_field (&F), _VD (F)
104 		{ /*std::cerr << "MD cstor " << this << std::endl;*/ }
105 
106 		/// Copy operator.
107 		MatrixDomain& operator= (const MatrixDomain& MD)
108 		{
109 			_field = MD._field;
110 			_VD = MD._VD;
111 			return *this;
112 		}
113 
114 		/** Retrieve the underlying field.
115 		 * Return a reference to the field that this matrix domain
116 		 * object uses
117 		 * @returns reference to field
118 		 */
119 		//@{
field()120 		const Field &field () const
121 		{
122 			return *_field;
123 		}
124 
125 		//@}
126 
127 		/** Print matrix.
128 		 * @param  os  Output stream to which matrix is written.
129 		 * @param  A   Matrix.
130 		 * @returns reference to os.
131 		 */
132 		template <class Matrix_>
write(std::ostream & os,const Matrix_ & A)133 		inline std::ostream &write (std::ostream &os, const Matrix_ &A) const
134 		{
135 			return A.write (os);
136 		}
137 
138 		/** Read matrix.
139 		 * @param  is  Input stream from which matrix is read.
140 		 * @param  A   Matrix.
141 		 * @returns reference to is.
142 		 */
143 		template <class Matrix_>
read(std::istream & is,Matrix_ & A)144 		inline std::istream &read (std::istream &is, Matrix_ &A) const
145 		{
146 			return A.read (is, _field);
147 		}
148 
149 		/** Matrix copy
150 		 * B <- A.
151 		 * Copy the contents of the matrix B to the matrix A
152 		 *
153 		 * Both matrices must support the same iterators, row or column.
154 		 *
155 		 * @param B Matrix B
156 		 * @param A Matrix A
157 		 * @returns Reference to B
158 		 */
159 		template <class Matrix1, class Matrix2>
copy(Matrix1 & B,const Matrix2 & A)160 		inline Matrix1 &copy (Matrix1 &B, const Matrix2 &A) const
161 		{
162 			return copySpecialized (B, A,
163 						typename MatrixTraits<Matrix1>::MatrixCategory (),
164 						typename MatrixTraits<Matrix2>::MatrixCategory ());
165 		}
166 		/// B <-- A.  They must already have the same shape.
copy(Matrix & B,const Matrix & A)167 		inline Matrix &copy (Matrix &B, const Matrix &A) const {
168 			return B.copy(A);
169 		}
170 
171 		/** Matrix swap
172 		 * B <--> A.  They must already have the same shape.
173 		 * @returns Reference to B
174 		 */
swap(Matrix & B,Matrix & A)175 		inline Matrix &swap(Matrix &B, Matrix &A) const {
176 			return B.swap(A);
177 		}
178 
179 		/** Matrix equality.
180 		 * Test whether the matrices A and B are equal
181 		 * @param A Input vector
182 		 * @param B Input vector
183 		 * @returns true if and only if the matrices A and B are equal
184 		 */
185 		template <class Matrix1, class Matrix2>
areEqual(const Matrix1 & A,const Matrix2 & B)186 		bool areEqual (const Matrix1 &A, const Matrix2 &B) const
187 		{
188 			return areEqualSpecialized (B, A,
189 						    typename MatrixTraits<Matrix1>::MatrixCategory (),
190 						    typename MatrixTraits<Matrix2>::MatrixCategory ());
191 		}
192 
193 		/** Matrix equality with zero.
194 		 * @param A Input matrix
195 		 * @returns true if and only if the matrix A is zero
196 		 */
197 		template <class Matrix_>
isZero(const Matrix_ & A)198 		inline bool isZero (const Matrix_ &A) const
199 		{
200 			return isZeroSpecialized (A, typename MatrixTraits<Matrix_>::MatrixCategory ());
201 		}
202 
203 		/** Matrix-matrix addition
204 		 * C <- A + B.
205 		 *
206 		 * Each of A, B, and C must support the same iterator, either row or
207 		 * column
208 		 *
209 		 * @param C Output matrix C
210 		 * @param A Input matrix A
211 		 * @param B Input matrix B
212 		 * @returns Reference to C
213 		 */
214 		template <class Matrix1, class Matrix2, class Matrix3>
add(Matrix1 & C,const Matrix2 & A,const Matrix3 & B)215 		inline Matrix1& add (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const
216 		{
217 			return addSpecialized (C, A, B,
218 					       typename MatrixTraits<Matrix1>::MatrixCategory (),
219 					       typename MatrixTraits<Matrix2>::MatrixCategory (),
220 					       typename MatrixTraits<Matrix3>::MatrixCategory ());
221 		}
222 
223 		/** Matrix-matrix in-place addition
224 		 * A <- A + B.
225 		 *
226 		 * Each of A and B must support the same iterator, either row or column
227 		 *
228 		 * @param A Input matrix A
229 		 * @param B Input matrix B
230 		 * @returns Reference to A
231 		 */
232 		template <class Matrix1, class Matrix2>
addin(Matrix1 & A,const Matrix2 & B)233 		inline Matrix1& addin (Matrix1 &A, const Matrix2 &B) const
234 		{
235 			return addinSpecialized (A, B,
236 						 typename MatrixTraits<Matrix1>::MatrixCategory (),
237 						 typename MatrixTraits<Matrix2>::MatrixCategory ());
238 		}
239 
240 		/** Matrix-matrix subtraction
241 		 * C <- A - B.
242 		 *
243 		 * Each of A, B, and C must support the same iterator, either row or
244 		 * column
245 		 *
246 		 * @param C Output matrix C
247 		 * @param A Input matrix A
248 		 * @param B Input matrix B
249 		 * @returns Reference to C
250 		 */
251 		template <class Matrix1, class Matrix2, class Matrix3>
sub(Matrix1 & C,const Matrix2 & A,const Matrix3 & B)252 		inline Matrix1 &sub (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const
253 		{
254 			return subSpecialized (C, A, B,
255 					       typename MatrixTraits<Matrix1>::MatrixCategory (),
256 					       typename MatrixTraits<Matrix2>::MatrixCategory (),
257 					       typename MatrixTraits<Matrix3>::MatrixCategory ());
258 		}
259 
260 		/** Matrix-matrix in-place subtraction
261 		 * A <- A - B.
262 		 *
263 		 * Each of A and B must support the same iterator, either row or column
264 		 *
265 		 * @param A Input matrix A
266 		 * @param B Input matrix B
267 		 * @returns Reference to A
268 		 */
269 		template <class Matrix1, class Matrix2>
subin(Matrix1 & A,const Matrix2 & B)270 		inline Matrix1 &subin (Matrix1 &A, const Matrix2 &B) const
271 		{
272 			return subinSpecialized (A, B,
273 						 typename MatrixTraits<Matrix1>::MatrixCategory (),
274 						 typename MatrixTraits<Matrix2>::MatrixCategory ());
275 		}
276 
277 		/** Matrix negate
278 		 * B <- -A.
279 		 *
280 		 * Each of A and B must support the same iterator, either row or column
281 		 *
282 		 * @param B Output matrix B
283 		 * @param A Input matrix A
284 		 * @returns reference to B
285 		 */
286 		template <class Matrix1, class Matrix2>
neg(Matrix1 & B,const Matrix2 & A)287 		inline Matrix1 &neg (Matrix1 &B, const Matrix2 &A) const
288 		{
289 			return negSpecialized (B, A,
290 					       typename MatrixTraits<Matrix1>::MatrixCategory (),
291 					       typename MatrixTraits<Matrix2>::MatrixCategory ());
292 		}
293 
294 		/** Matrix in-place negate
295 		 * A <- -A.
296 		 * @param A Input matrix A; result is stored here
297 		 */
298 		template <class Matrix_>
negin(Matrix_ & A)299 		inline Matrix_ &negin (Matrix_ &A) const
300 		{
301 			return neginSpecialized (A, typename MatrixTraits<Matrix_>::MatrixCategory ());
302 		}
303 
304 		/** Matrix-matrix multiply
305 		 * C <- A * B.
306 		 *
307 		 * C must support both row and column iterators, and the vector
308 		 * representations must be dense. Examples of supported matrices are
309 		 * \ref BlasMatrix and \ref BlasSubmatrix.
310 		 *
311 		 * Either A or B, or both, may have limited iterators. However, either A
312 		 * must support row iterators or B must support column iterators. If
313 		 * both A and B lack support for an iterator (either row or column),
314 		 * then C must support the same type of iterator as A and B.
315 		 *
316 		 * @param C Output matrix C
317 		 * @param A Input matrix A
318 		 * @param B Input matrix B
319 		 * @returns Reference to C
320 		 */
321 		template <class Matrix1, class Matrix2, class Matrix3>
mul(Matrix1 & C,const Matrix2 & A,const Matrix3 & B)322 		inline Matrix1 &mul (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const
323 		{
324 			return mulSpecialized (C, A, B,
325 					       typename MatrixTraits<Matrix1>::MatrixCategory (),
326 					       typename MatrixTraits<Matrix2>::MatrixCategory (),
327 					       typename MatrixTraits<Matrix3>::MatrixCategory ());
328 		}
329 
330 		/** Matrix-matrix in-place multiply on the left
331 		 * B <- A * B.
332 		 *
333 		 * B should support both row and column iterators, and must be dense. A
334 		 * must support row iterators.
335 		 *
336 		 * @param A Input matrix A
337 		 * @param B Input matrix B
338 		 * @returns Reference to B
339 		 */
340 		template <class Matrix1, class Matrix2>
341 		inline Matrix2 &leftMulin (const Matrix1 &A, Matrix2 &B) const;
342 
343 		/** Matrix-matrix in-place multiply on the right
344 		 * A <- A * B.
345 		 *
346 		 * A should support both row and column iterators, and must be dense. B
347 		 * must support column iterators.
348 		 *
349 		 * @param A Input matrix A
350 		 * @param B Input matrix B
351 		 * @returns Reference to A
352 		 */
353 		template <class Matrix1, class Matrix2>
354 		inline Matrix1 &rightMulin (Matrix1 &A, const Matrix2 &B) const;
355 
356 		/** Matrix-matrix in-place multiply
357 		 * A <- A * B.
358 		 *
359 		 * This is an alias for \ref rightMulin
360 		 *
361 		 * @param A Input matrix A
362 		 * @param B Input matrix B
363 		 * @returns Reference to A
364 		 */
365 		template <class Matrix1, class Matrix2>
mulin(Matrix1 & A,const Matrix2 & B)366 		inline Matrix1 &mulin (Matrix1 &A, const Matrix2 &B) const
367 		{
368 			return rightMulin (A, B);
369 		}
370 
371 		/** Matrix-scalar multiply
372 		 * C <- B * a.
373 		 *
374 		 * Multiply B by the scalar element a and store the result in C. B and C
375 		 * must support the same iterators.
376 		 *
377 		 * @param C Output matrix C
378 		 * @param B Input matrix B
379 		 * @param a Input scalar a
380 		 * @returns Reference to C
381 		 */
382 		template <class Matrix1, class Matrix2>
mul(Matrix1 & C,const Matrix2 & B,const typename Field::Element & a)383 		inline Matrix1 &mul (Matrix1 &C, const Matrix2 &B, const typename Field::Element &a) const
384 		{
385 			return mulSpecialized (C, B, a,
386 					       typename MatrixTraits<Matrix1>::MatrixCategory (),
387 					       typename MatrixTraits<Matrix2>::MatrixCategory ());
388 		}
389 
390 		/** Matrix-scalar in-place multiply
391 		 * B <- B * a.
392 		 *
393 		 * Multiply B by the scalar element a in-place.
394 		 *
395 		 * @param B Input matrix B
396 		 * @param a Input scalar a
397 		 * @returns Reference to B
398 		 */
399 		template <class Matrix_>
mulin(Matrix_ & B,const typename Field::Element & a)400 		inline Matrix_ &mulin (Matrix_ &B, const typename Field::Element &a) const
401 		{
402 			return mulinSpecialized (B, a, typename MatrixTraits<Matrix_>::MatrixCategory ());
403 		}
404 
405 		/** Matrix-matrix in-place axpy
406 		 * Y <- Y + A*X.
407 		 *
408 		 * This function combines \ref mul and \ref add, eliminating the need
409 		 * for an additional temporary in expressions of the form $Y = Y +
410 		 * AX$. Only one row of additional storage is required. Y may have
411 		 * either efficient row iterators or efficient column iterators, and the
412 		 * same restrictions on A and X apply as in \ref mul.
413 		 *
414 		 * Note that no out-of-place axpy is provided, since it gives no
415 		 * benefit. One may just as easily multiply into the result and call
416 		 * \ref addin.
417 		 *
418 		 * @param Y Input matrix Y; result is stored here
419 		 * @param A Input matrix A
420 		 * @param X Input matrix X
421 		 */
422 		template <class Matrix1, class Matrix2, class Matrix3>
axpyin(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X)423 		inline Matrix1 &axpyin (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X) const
424 		{
425 			return axpyinSpecialized (Y, A, X,
426 						  typename MatrixTraits<Matrix1>::MatrixCategory (),
427 						  typename MatrixTraits<Matrix2>::MatrixCategory (),
428 						  typename MatrixTraits<Matrix3>::MatrixCategory ());
429 		}
430 
431 		//! Y <- AX-Y
432 		template <class Matrix1, class Matrix2, class Matrix3>
axmyin(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X)433 		inline Matrix1 &axmyin (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X) const
434 		{
435 			negin(Y);
436 			axpyin(Y,A,X);
437 			return Y;
438 		}
439 
440 		// Y <- Y + aX
441 		template <class Matrix1, class Matrix3>
saxpyin(Matrix1 & Y,const Element & a,const Matrix3 & X)442 		inline Matrix1 &saxpyin (Matrix1 &Y, const Element &a, const Matrix3 &X) const
443 		{	// a crude hack for now
444 			Element x, y;
445 			for (size_t i = 0; i < X.rowdim(); ++i)
446 			for (size_t j = 0; j < X.coldim(); ++j)
447 				Y.setEntry(i,j,field().axpyin(Y.getEntry(y,i,j), a, X.getEntry(x, i, j)));
448 			return Y;
449 		}
450 
451 		/*!  General matrix multiply
452 		 * \f$ D \gets \alpha A B + \beta C\f$.
453 		 * @todo not efficient...
454 		 */
455 		template <class Matrix1, class Matrix2, class Matrix3>
muladd(Matrix1 & D,const typename Field::Element & beta,const Matrix1 & C,const typename Field::Element & alpha,const Matrix2 & A,const Matrix3 & B)456 		inline Matrix1 &muladd (Matrix1                       & D,
457 					const typename Field::Element & beta,
458 					const Matrix1                 & C,
459 					const typename Field::Element & alpha,
460 					const Matrix2                 & A,
461 					const Matrix3                 & B) const
462 		{
463 			mul(D,A,B); // D = AB
464 			mulin(D,alpha); // D = alpha D
465 			Matrix1 CC(C);
466 			mulin(CC,beta);   // C = beta C
467 			addin(D,CC);   // D = D+C
468 			return D;
469 		}
470 
471 		/*! @todo Need documentation of these methods */
472 		//@{
473 		template<class Matrix1, class Matrix2>
474 		Matrix1 &pow_apply (Matrix1 &M1, const Matrix2 &M2, unsigned long int k) const;
475 
476 		template<class Matrix1, class Matrix2>
477 		Matrix1 &pow_horn (Matrix1 &M1, const Matrix2 &M2, unsigned long int k) const;
478 		//@}
479 
480 
481 		/*! @name Matrix-vector arithmetic operations
482 		 * These operations take a matrix satisfying the \ref DenseMatrix
483 		 * archetype and LinBox vectors as inputs. They involve matrix-vector
484 		 * product and matrix-vector AXPY
485 		 */
486 		//@{
487 		/** Matrix-vector multiply
488 		 * w <- A * v.
489 		 *
490 		 * The vectors v and w must be of the same representation (dense, sparse
491 		 * sequence, sparse associative, or sparse parallel), but they may be of
492 		 * different types. The matrix A may have any representation.
493 		 *
494 		 * @param w Output vector w
495 		 * @param A Input matrix A
496 		 * @param v Input vector v
497 		 * @returns Reference to w
498 		 */
499 		template <class Vector1, class Matrix_, class Vector2>
vectorMul(Vector1 & w,const Matrix_ & A,const Vector2 & v)500 		inline Vector1 &vectorMul (Vector1 &w, const Matrix_ &A, const Vector2 &v) const
501 		{
502 			return mulSpecialized (w, A, v, typename MatrixTraits<Matrix_>::MatrixCategory ());
503 		}
504 
505 		/** Matrix-vector in-place axpy
506 		 * \f$y \gets y + A x\f$.
507 		 *
508 		 * This function eliminates the requirement for temporary storage when
509 		 * one is computing an expression of the form given above.
510 		 *
511 		 * The vectors y and x must be of the same representation (dense, sparse
512 		 * sequence, sparse associative, or sparse parallel), but they may be of
513 		 * different types. The matrix A may have any representation.
514 		 *
515 		 * Note that out-of-place axpy is not provided since it provides no
516 		 * benefit -- one can use mul and then addin to exactly the same effect,
517 		 * with no additional storage or performance cost.
518 		 *
519 		 * @param y Input vector y; result is stored here
520 		 * @param A Input matrix A
521 		 * @param x Input vector x
522 		 */
523 		template <class Vector1, class Matrix_, class Vector2>
vectorAxpyin(Vector1 & y,const Matrix_ & A,const Vector2 & x)524 		inline Vector1 &vectorAxpyin (Vector1 &y, const Matrix_ &A, const Vector2 &x) const
525 		{
526 			return axpyinSpecialized (y, A, x, typename MatrixTraits<Matrix_>::MatrixCategory ());
527 		}
528 		//@}
529 
530 		/*! @name Matrix-black box arithmetic operations
531 		 * These operations mimic the matrix-matrix arithmetic operations above,
532 		 * but one of the parameters is a \ref BlackboxArchetype.
533 		 */
534 		//@{
535 		/** Matrix-black box left-multiply
536 		 * C <- A * B.
537 		 *
538 		 * Both C and B must support column iterators
539 		 *
540 		 * @param C Output matrix
541 		 * @param A Black box for A
542 		 * @param B Matrix B
543 		 */
544 		template <class Matrix1, class Blackbox, class Matrix2>
545 		inline Matrix1 &blackboxMulLeft (Matrix1 &C, const Blackbox &A, const Matrix2 &B) const;
546 
547 		/** Matrix-black box right-multiply
548 		 * C <- A * B.
549 		 *
550 		 * Both C and A must support row iterators
551 		 *
552 		 * @param C Output matrix
553 		 * @param A Matrix A
554 		 * @param B Black box for B
555 		 */
556 		template <class Matrix1, class Matrix2, class Blackbox>
557 		inline Matrix1 &blackboxMulRight (Matrix1 &C, const Matrix2 &A, const Blackbox &B) const;
558 		//@}
559 
560 		/*! @name Matrix permutations
561 		 * @brief
562 		 * These operations permute the rows or columns of a matrix based on
563 		 * the given permutation. They are intended for use with Gauss-Jordan
564 		 * elimination
565 		 */
566 		//@{
567 		/// Transposition.
568 		typedef std::pair<unsigned int, unsigned int> Transposition;
569 		/** Permutation.
570 		 *
571 		 * A permutation is represented as a vector of pairs, each
572 		 * pair representing a transposition.
573 		 */
574 		typedef std::vector<Transposition> Permutation;
575 
576 
577 		/** Permute the rows of the given matrix.
578 		 *
579 		 * @param A Output matrix
580 		 * @param P_start Start of permutation
581 		 * @param P_end End of permutation
582 		 * @returns Reference to A
583 		 */
584 		template <class Matrix_, class Iterator>
permuteRows(Matrix_ & A,Iterator P_start,Iterator P_end)585 		inline Matrix_ &permuteRows (Matrix_   &A,
586 					    Iterator  P_start,
587 					    Iterator  P_end) const
588 		{
589 			return permuteRowsSpecialized (A, P_start, P_end,
590 						       typename MatrixTraits<Matrix_>::MatrixCategory ());
591 		}
592 
593 		/** Permute the columns of the given matrix.
594 		 *
595 		 * @param A Output matrix
596 		 * @param P_start Start of permutation
597 		 * @param P_end End of permutation
598 		 * @returns Reference to A
599 		 */
600 		template <class Matrix_, class Iterator>
permuteColumns(Matrix_ & A,Iterator P_start,Iterator P_end)601 		inline Matrix_ &permuteColumns (Matrix_   &A,
602 					       Iterator  P_start,
603 					       Iterator  P_end) const
604 		{
605 			return permuteColsSpecialized (A, P_start, P_end,
606 						       typename MatrixTraits<Matrix_>::MatrixCategory ());
607 		}
608 		//@}
609 
vectorDomain()610 		const VectorDomain<Field> & vectorDomain() const
611 		{
612 			return _VD ;
613 		}
614 	protected:
615 
616 		// Specialized function implementations
617 		template <class Matrix1, class Matrix2> Matrix1 &copyRow (Matrix1 &B, const Matrix2 &A) const;
618 		template <class Matrix1, class Matrix2> Matrix1 &copyCol (Matrix1 &B, const Matrix2 &A) const;
619 
620 		template <class Matrix1, class Matrix2>
copySpecialized(Matrix1 & B,const Matrix2 & A,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)621 		inline Matrix1 &copySpecialized (Matrix1 &B, const Matrix2 &A,
622 						 MatrixCategories::RowMatrixTag,
623 						 MatrixCategories::RowMatrixTag) const
624 		{
625 			return copyRow (B, A);
626 		}
627 		template <class Matrix1, class Matrix2>
copySpecialized(Matrix1 & B,const Matrix2 & A,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)628 		inline Matrix1 &copySpecialized (Matrix1 &B, const Matrix2 &A,
629 						 MatrixCategories::ColMatrixTag,
630 						 MatrixCategories::ColMatrixTag) const
631 		{
632 			return copyCol (B, A);
633 		}
634 		template <class Matrix1, class Matrix2>
copySpecialized(Matrix1 & B,const Matrix2 & A,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)635 		inline Matrix1 &copySpecialized (Matrix1 &B, const Matrix2 &A,
636 						 MatrixCategories::RowColMatrixTag,
637 						 MatrixCategories::RowColMatrixTag) const
638 		{
639 			return copyRow (B, A);
640 		}
641 
642 		template <class Matrix1, class Matrix2> bool areEqualBB (const Matrix1 &A, const Matrix2 &B) const;
643 		template <class Matrix1, class Matrix2> bool areEqualRow (const Matrix1 &A, const Matrix2 &B) const;
644 		template <class Matrix1, class Matrix2> bool areEqualCol (const Matrix1 &A, const Matrix2 &B) const;
645 
646 		template <class Matrix1, class Matrix2>
areEqualSpecialized(const Matrix1 & A,const Matrix2 & B,MatrixCategories::BlackboxTag,MatrixCategories::BlackboxTag)647 		inline bool areEqualSpecialized (const Matrix1 &A, const Matrix2 &B,
648 						 MatrixCategories::BlackboxTag,
649 						 MatrixCategories::BlackboxTag) const
650 		{
651 			return areEqualBB(A, B);
652 		}
653 		template <class Matrix1, class Matrix2>
areEqualSpecialized(const Matrix1 & A,const Matrix2 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)654 		inline bool areEqualSpecialized (const Matrix1 &A, const Matrix2 &B,
655 						 MatrixCategories::RowMatrixTag,
656 						 MatrixCategories::RowMatrixTag) const
657 		{
658 			return areEqualRow (A, B);
659 		}
660 		template <class Matrix1, class Matrix2>
areEqualSpecialized(const Matrix1 & A,const Matrix2 & B,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)661 		inline bool areEqualSpecialized (const Matrix1 &A, const Matrix2 &B,
662 						 MatrixCategories::ColMatrixTag,
663 						 MatrixCategories::ColMatrixTag) const
664 		{
665 			return areEqualCol (A, B);
666 		}
667 		template <class Matrix1, class Matrix2>
areEqualSpecialized(const Matrix1 & A,const Matrix2 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)668 		inline bool areEqualSpecialized (const Matrix1 &A, const Matrix2 &B,
669 						 MatrixCategories::RowColMatrixTag,
670 						 MatrixCategories::RowColMatrixTag) const
671 		{
672 			return areEqualRow (A, B);
673 		}
674 
675 		template <class Matrix_> bool isZeroBB (const Matrix_ &v) const;
676 		template <class Matrix_> bool isZeroRow (const Matrix_ &v) const;
677 		template <class Matrix_> bool isZeroCol (const Matrix_ &v) const;
678 
679 		template <class Matrix_>
isZeroSpecialized(const Matrix_ & A,MatrixCategories::BlackboxTag)680 		bool isZeroSpecialized (const Matrix_ &A, MatrixCategories::BlackboxTag) const
681 		{
682 			return isZeroBB (A);
683 		}
684 		template <class Matrix_>
isZeroSpecialized(const Matrix_ & A,MatrixCategories::RowMatrixTag)685 		bool isZeroSpecialized (const Matrix_ &A, MatrixCategories::RowMatrixTag) const
686 		{
687 			return isZeroRow (A);
688 		}
689 		template <class Matrix_>
isZeroSpecialized(const Matrix_ & A,MatrixCategories::ColMatrixTag)690 		bool isZeroSpecialized (const Matrix_ &A, MatrixCategories::ColMatrixTag) const
691 		{
692 			return isZeroCol (A);
693 		}
694 		template <class Matrix_>
isZeroSpecialized(const Matrix_ & A,MatrixCategories::RowColMatrixTag)695 		bool isZeroSpecialized (const Matrix_ &A, MatrixCategories::RowColMatrixTag) const
696 		{
697 			return isZeroRow (A);
698 		}
699 
700 		template <class Matrix1, class Matrix2, class Matrix3>
701 		Matrix1& addRow (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
702 		template <class Matrix1, class Matrix2, class Matrix3>
703 		Matrix1& addCol (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
704 
705 		template <class Matrix1, class Matrix2, class Matrix3>
addSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)706 		Matrix1& addSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
707 					 MatrixCategories::RowMatrixTag,
708 					 MatrixCategories::RowMatrixTag,
709 					 MatrixCategories::RowMatrixTag) const
710 		{
711 			return addRow (C, A, B);
712 		}
713 		template <class Matrix1, class Matrix2, class Matrix3>
addSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)714 		Matrix1& addSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
715 					 MatrixCategories::ColMatrixTag,
716 					 MatrixCategories::ColMatrixTag,
717 					 MatrixCategories::ColMatrixTag) const
718 		{
719 			return addCol (C, A, B);
720 		}
721 		template <class Matrix1, class Matrix2, class Matrix3>
addSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)722 		Matrix1& addSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
723 					 MatrixCategories::RowColMatrixTag,
724 					 MatrixCategories::RowColMatrixTag,
725 					 MatrixCategories::RowColMatrixTag) const
726 		{
727 			return addRow (C, A, B);
728 		}
729 
730 		template <class Matrix1, class Matrix2> Matrix1& addinRow (Matrix1 &A, const Matrix2 &B) const;
731 		template <class Matrix1, class Matrix2> Matrix1& addinCol (Matrix1 &A, const Matrix2 &B) const;
732 
733 		template <class Matrix1, class Matrix2>
addinSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)734 		inline Matrix1& addinSpecialized (Matrix1 &A, const Matrix2 &B,
735 						  MatrixCategories::RowMatrixTag,
736 						  MatrixCategories::RowMatrixTag) const
737 		{
738 			return addinRow (A, B);
739 		}
740 		template <class Matrix1, class Matrix2>
addinSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)741 		inline Matrix1& addinSpecialized (Matrix1 &A, const Matrix2 &B,
742 						  MatrixCategories::ColMatrixTag,
743 						  MatrixCategories::ColMatrixTag) const
744 		{
745 			return addinCol (A, B);
746 		}
747 		template <class Matrix1, class Matrix2>
addinSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)748 		inline Matrix1& addinSpecialized (Matrix1 &A, const Matrix2 &B,
749 						  MatrixCategories::RowColMatrixTag,
750 						  MatrixCategories::RowColMatrixTag) const
751 		{
752 			return addinRow (A, B);
753 		}
754 
755 		template <class Matrix1, class Matrix2, class Matrix3>
756 		Matrix1& subRow (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
757 		template <class Matrix1, class Matrix2, class Matrix3>
758 		Matrix1& subCol (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
759 
760 		template <class Matrix1, class Matrix2, class Matrix3>
subSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)761 		Matrix1& subSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
762 					 MatrixCategories::RowMatrixTag,
763 					 MatrixCategories::RowMatrixTag,
764 					 MatrixCategories::RowMatrixTag) const
765 		{
766 			return subRow (C, A, B);
767 		}
768 		template <class Matrix1, class Matrix2, class Matrix3>
subSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)769 		Matrix1& subSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
770 					 MatrixCategories::ColMatrixTag,
771 					 MatrixCategories::ColMatrixTag,
772 					 MatrixCategories::ColMatrixTag) const
773 		{
774 			return subCol (C, A, B);
775 		}
776 		template <class Matrix1, class Matrix2, class Matrix3>
subSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)777 		Matrix1& subSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
778 					 MatrixCategories::RowColMatrixTag,
779 					 MatrixCategories::RowColMatrixTag,
780 					 MatrixCategories::RowColMatrixTag) const
781 		{
782 			return subRow (C, A, B);
783 		}
784 
785 		template <class Matrix1, class Matrix2> Matrix1& subinRow (Matrix1 &A, const Matrix2 &B) const;
786 		template <class Matrix1, class Matrix2> Matrix1& subinCol (Matrix1 &A, const Matrix2 &B) const;
787 
788 		template <class Matrix1, class Matrix2>
subinSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)789 		Matrix1& subinSpecialized (Matrix1 &A, const Matrix2 &B,
790 					   MatrixCategories::RowMatrixTag,
791 					   MatrixCategories::RowMatrixTag) const
792 		{
793 			return subinRow (A, B);
794 		}
795 		template <class Matrix1, class Matrix2>
subinSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)796 		Matrix1& subinSpecialized (Matrix1 &A, const Matrix2 &B,
797 					   MatrixCategories::ColMatrixTag,
798 					   MatrixCategories::ColMatrixTag) const
799 		{
800 			return subinCol (A, B);
801 		}
802 		template <class Matrix1, class Matrix2>
subinSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)803 		Matrix1& subinSpecialized (Matrix1 &A, const Matrix2 &B,
804 					   MatrixCategories::RowColMatrixTag,
805 					   MatrixCategories::RowColMatrixTag) const
806 		{
807 			return subinRow (A, B);
808 		}
809 
810 		template <class Matrix1, class Matrix2> Matrix1& negRow (Matrix1 &A, const Matrix2 &B) const;
811 		template <class Matrix1, class Matrix2> Matrix1& negCol (Matrix1 &A, const Matrix2 &B) const;
812 
813 		template <class Matrix1, class Matrix2>
negSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)814 		inline Matrix1& negSpecialized (Matrix1 &A, const Matrix2 &B,
815 						MatrixCategories::RowMatrixTag,
816 						MatrixCategories::RowMatrixTag) const
817 		{
818 			return negRow (A, B);
819 		}
820 		template <class Matrix1, class Matrix2>
negSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)821 		inline Matrix1& negSpecialized (Matrix1 &A, const Matrix2 &B,
822 						MatrixCategories::ColMatrixTag,
823 						MatrixCategories::ColMatrixTag) const
824 		{
825 			return negCol (A, B);
826 		}
827 		template <class Matrix1, class Matrix2>
negSpecialized(Matrix1 & A,const Matrix2 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)828 		inline Matrix1& negSpecialized (Matrix1 &A, const Matrix2 &B,
829 						MatrixCategories::RowColMatrixTag,
830 						MatrixCategories::RowColMatrixTag) const
831 		{
832 			return negRow (A, B);
833 		}
834 
835 		template <class Matrix_> Matrix_ &neginRow (Matrix_ &A) const;
836 		template <class Matrix_> Matrix_ &neginCol (Matrix_ &A) const;
837 
838 		template <class Matrix_>
neginSpecialized(Matrix_ & A,MatrixCategories::RowMatrixTag)839 		Matrix_ &neginSpecialized (Matrix_ &A, MatrixCategories::RowMatrixTag) const
840 		{
841 			return neginRow (A);
842 		}
843 		template <class Matrix_>
neginSpecialized(Matrix_ & A,MatrixCategories::ColMatrixTag)844 		Matrix_ &neginSpecialized (Matrix_ &A, MatrixCategories::ColMatrixTag) const
845 		{
846 			return neginCol (A);
847 		}
848 		template <class Matrix_>
neginSpecialized(Matrix_ & A,MatrixCategories::RowColMatrixTag)849 		Matrix_ &neginSpecialized (Matrix_ &A, MatrixCategories::RowColMatrixTag) const
850 		{
851 			return neginRow (A);
852 		}
853 
854 		template <class Matrix1, class Matrix2, class Matrix3>
855 		Matrix1 &mulRowRowCol (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
856 		template <class Matrix1, class Matrix2, class Matrix3>
857 		Matrix1 &mulColRowCol (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
858 		template <class Matrix1, class Matrix2, class Matrix3>
859 		Matrix1 &mulRowRowRow (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
860 		template <class Matrix1, class Matrix2, class Matrix3>
861 		Matrix1 &mulColColCol (Matrix1 &C, const Matrix2 &A, const Matrix3 &B) const;
862 
863 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::BlackboxTag)864 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
865 					 MatrixCategories::RowMatrixTag,
866 					 MatrixCategories::RowMatrixTag,
867 					 MatrixCategories::BlackboxTag) const
868 		{
869 			return blackboxMulRight(C, A, B);
870 		}
871 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::ColMatrixTag,MatrixCategories::BlackboxTag,MatrixCategories::ColMatrixTag)872 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
873 					 MatrixCategories::ColMatrixTag,
874 					 MatrixCategories::BlackboxTag,
875 					 MatrixCategories::ColMatrixTag) const
876 		{
877 			return blackboxMulLeft(C, A, B);
878 		}
879 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::ColMatrixTag)880 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
881 					 MatrixCategories::RowMatrixTag,
882 					 MatrixCategories::RowMatrixTag,
883 					 MatrixCategories::ColMatrixTag) const
884 		{
885 			return mulRowRowCol (C, A, B);
886 		}
887 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::ColMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::ColMatrixTag)888 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
889 					 MatrixCategories::ColMatrixTag,
890 					 MatrixCategories::RowMatrixTag,
891 					 MatrixCategories::ColMatrixTag) const
892 		{
893 			return mulColRowCol (C, A, B);
894 		}
895 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::ColMatrixTag)896 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
897 					 MatrixCategories::RowColMatrixTag,
898 					 MatrixCategories::RowMatrixTag,
899 					 MatrixCategories::ColMatrixTag) const
900 		{
901 			return mulRowRowCol (C, A, B);
902 		}
903 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)904 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
905 					 MatrixCategories::RowMatrixTag,
906 					 MatrixCategories::RowMatrixTag,
907 					 MatrixCategories::RowMatrixTag) const
908 		{
909 			return mulRowRowRow (C, A, B);
910 		}
911 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)912 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
913 					 MatrixCategories::ColMatrixTag,
914 					 MatrixCategories::ColMatrixTag,
915 					 MatrixCategories::ColMatrixTag) const
916 		{
917 			return mulColColCol (C, A, B);
918 		}
919 		template <class Matrix1, class Matrix2, class Matrix3>
mulSpecialized(Matrix1 & C,const Matrix2 & A,const Matrix3 & B,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)920 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &A, const Matrix3 &B,
921 					 MatrixCategories::RowColMatrixTag,
922 					 MatrixCategories::RowColMatrixTag,
923 					 MatrixCategories::RowColMatrixTag) const
924 		{
925 			return mulRowRowCol (C, A, B);
926 		}
927 
928 		template <class Matrix1, class Matrix2>
929 		Matrix1 &mulRow (Matrix1 &C, const Matrix2 &B, const typename Field::Element &a) const;
930 		template <class Matrix1, class Matrix2>
931 		Matrix1 &mulCol (Matrix1 &C, const Matrix2 &B, const typename Field::Element &a) const;
932 
933 		template <class Matrix1, class Matrix2>
mulSpecialized(Matrix1 & C,const Matrix2 & B,const typename Field::Element & a,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)934 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &B, const typename Field::Element &a,
935 					 MatrixCategories::RowMatrixTag,
936 					 MatrixCategories::RowMatrixTag) const
937 		{
938 			return mulRow (C, B, a);
939 		}
940 		template <class Matrix1, class Matrix2>
mulSpecialized(Matrix1 & C,const Matrix2 & B,const typename Field::Element & a,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)941 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &B, const typename Field::Element &a,
942 					 MatrixCategories::ColMatrixTag,
943 					 MatrixCategories::ColMatrixTag) const
944 		{
945 			return mulCol (C, B, a);
946 		}
947 		template <class Matrix1, class Matrix2>
mulSpecialized(Matrix1 & C,const Matrix2 & B,const typename Field::Element & a,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)948 		Matrix1 &mulSpecialized (Matrix1 &C, const Matrix2 &B, const typename Field::Element &a,
949 					 MatrixCategories::RowColMatrixTag,
950 					 MatrixCategories::RowColMatrixTag) const
951 		{
952 			return mulRow (C, B, a);
953 		}
954 
955 		template <class Matrix_> Matrix_ &mulinRow (Matrix_ &B, const typename Field::Element &a) const;
956 		template <class Matrix_> Matrix_ &mulinCol (Matrix_ &B, const typename Field::Element &a) const;
957 
958 		template <class Matrix_>
mulinSpecialized(Matrix_ & B,const typename Field::Element & a,MatrixCategories::RowMatrixTag)959 		Matrix_ &mulinSpecialized (Matrix_ &B, const typename Field::Element &a,
960 					  MatrixCategories::RowMatrixTag) const
961 		{
962 			return mulinRow (B, a);
963 		}
964 		template <class Matrix_>
mulinSpecialized(Matrix_ & B,const typename Field::Element & a,MatrixCategories::ColMatrixTag)965 		Matrix_ &mulinSpecialized (Matrix_ &B, const typename Field::Element &a,
966 					  MatrixCategories::ColMatrixTag) const
967 		{
968 			return mulinCol (B, a);
969 		}
970 		template <class Matrix_>
mulinSpecialized(Matrix_ & B,const typename Field::Element & a,MatrixCategories::RowColMatrixTag)971 		Matrix_ &mulinSpecialized (Matrix_ &B, const typename Field::Element &a,
972 					  MatrixCategories::RowColMatrixTag) const
973 		{
974 			return mulinRow (B, a);
975 		}
976 
977 		template <class Matrix1, class Matrix2, class Matrix3>
978 		Matrix1 &axpyinRowRowCol (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X) const;
979 		template <class Matrix1, class Matrix2, class Matrix3>
980 		Matrix1 &axpyinColRowCol (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X) const;
981 		template <class Matrix1, class Matrix2, class Matrix3>
982 		Matrix1 &axpyinRowRowRow (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X) const;
983 		template <class Matrix1, class Matrix2, class Matrix3>
984 		Matrix1 &axpyinColColCol (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X) const;
985 
986 		template <class Matrix1, class Matrix2, class Matrix3>
axpyinSpecialized(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::ColMatrixTag)987 		Matrix1 &axpyinSpecialized (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X,
988 					    MatrixCategories::RowMatrixTag,
989 					    MatrixCategories::RowMatrixTag,
990 					    MatrixCategories::ColMatrixTag) const
991 		{
992 			return axpyinRowRowCol (Y, A, X);
993 		}
994 		template <class Matrix1, class Matrix2, class Matrix3>
axpyinSpecialized(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X,MatrixCategories::ColMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::ColMatrixTag)995 		Matrix1 &axpyinSpecialized (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X,
996 					    MatrixCategories::ColMatrixTag,
997 					    MatrixCategories::RowMatrixTag,
998 					    MatrixCategories::ColMatrixTag) const
999 		{
1000 			return axpyinColRowCol (Y, A, X);
1001 		}
1002 		template <class Matrix1, class Matrix2, class Matrix3>
axpyinSpecialized(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X,MatrixCategories::RowColMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::ColMatrixTag)1003 		Matrix1 &axpyinSpecialized (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X,
1004 					    MatrixCategories::RowColMatrixTag,
1005 					    MatrixCategories::RowMatrixTag,
1006 					    MatrixCategories::ColMatrixTag) const
1007 		{
1008 			return axpyinRowRowCol (Y, A, X);
1009 		}
1010 		template <class Matrix1, class Matrix2, class Matrix3>
axpyinSpecialized(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag,MatrixCategories::RowMatrixTag)1011 		Matrix1 &axpyinSpecialized (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X,
1012 					    MatrixCategories::RowMatrixTag,
1013 					    MatrixCategories::RowMatrixTag,
1014 					    MatrixCategories::RowMatrixTag) const
1015 		{
1016 			return axpyinRowRowRow (Y, A, X);
1017 		}
1018 
1019 		template <class Matrix1, class Matrix2, class Matrix3>
axpyinSpecialized(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag,MatrixCategories::ColMatrixTag)1020 		Matrix1 &axpyinSpecialized (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X,
1021 					    MatrixCategories::ColMatrixTag,
1022 					    MatrixCategories::ColMatrixTag,
1023 					    MatrixCategories::ColMatrixTag) const
1024 		{
1025 			return axpyinColColCol (Y, A, X);
1026 		}
1027 
1028 		template <class Matrix1, class Matrix2, class Matrix3>
axpyinSpecialized(Matrix1 & Y,const Matrix2 & A,const Matrix3 & X,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag,MatrixCategories::RowColMatrixTag)1029 		Matrix1 &axpyinSpecialized (Matrix1 &Y, const Matrix2 &A, const Matrix3 &X,
1030 					    MatrixCategories::RowColMatrixTag,
1031 					    MatrixCategories::RowColMatrixTag,
1032 					    MatrixCategories::RowColMatrixTag) const
1033 		{
1034 			return axpyinRowRowCol (Y, A, X);
1035 		}
1036 
1037 		template <class Vector1, class Matrix_, class Vector2>
1038 		Vector1 &mulRowSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1039 					    VectorCategories::DenseVectorTag) const;
1040 		template <class Vector1, class Matrix_, class Vector2>
1041 		Vector1 &mulRowSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1042 					    VectorCategories::SparseSequenceVectorTag) const;
1043 		template <class Vector1, class Matrix_, class Vector2>
1044 		Vector1 &mulRowSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1045 					    VectorCategories::SparseAssociativeVectorTag) const;
1046 		template <class Vector1, class Matrix_, class Vector2>
1047 		Vector1 &mulRowSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1048 					    VectorCategories::SparseParallelVectorTag) const;
1049 
1050 		template <class Vector1, class Matrix_, class Vector2>
mulColSpecialized(Vector1 & w,const Matrix_ & A,const Vector2 & v,VectorCategories::DenseVectorTag,VectorCategories::DenseVectorTag)1051 		Vector1 &mulColSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1052 					    VectorCategories::DenseVectorTag,
1053 					    VectorCategories::DenseVectorTag) const
1054 		{
1055 			return this->mulColDense (_VD, w, A, v);
1056 		}
1057 		template <class Vector1, class Matrix_, class Vector2>
1058 		Vector1 &mulColSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1059 					    VectorCategories::DenseVectorTag,
1060 					    VectorCategories::SparseSequenceVectorTag) const;
1061 		template <class Vector1, class Matrix_, class Vector2>
1062 		Vector1 &mulColSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1063 					    VectorCategories::DenseVectorTag,
1064 					    VectorCategories::SparseAssociativeVectorTag) const;
1065 		template <class Vector1, class Matrix_, class Vector2>
1066 		Vector1 &mulColSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1067 					    VectorCategories::DenseVectorTag,
1068 					    VectorCategories::SparseParallelVectorTag) const;
1069 
1070 		template <class Vector1, class Matrix_, class Vector2>
mulColSpecialized(Vector1 & w,const Matrix_ & A,const Vector2 & v,VectorCategories::GenericVectorTag,VectorCategories::GenericVectorTag)1071 		inline Vector1 &mulColSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1072 						   VectorCategories::GenericVectorTag,
1073 						   VectorCategories::GenericVectorTag) const
1074 		{
1075 			DenseVector y(field());
1076 
1077 			VectorWrapper::ensureDim (y, w.size ());
1078 
1079 			VectorWrapper::ensureDim (y, w.size ());
1080 
1081 			vectorMul (y, A, v);
1082 			_VD.copy (w, y);
1083 
1084 			return w;
1085 		}
1086 
1087 		template <class Vector1, class Matrix_, class Vector2>
mulSpecialized(Vector1 & w,const Matrix_ & A,const Vector2 & v,MatrixCategories::RowMatrixTag)1088 		Vector1 &mulSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1089 					 MatrixCategories::RowMatrixTag) const
1090 		{
1091 			return mulRowSpecialized (w, A, v, typename VectorTraits<Vector1>::VectorCategory ());
1092 		}
1093 		template <class Vector1, class Matrix_, class Vector2>
mulSpecialized(Vector1 & w,const Matrix_ & A,const Vector2 & v,MatrixCategories::ColMatrixTag)1094 		Vector1 &mulSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1095 					 MatrixCategories::ColMatrixTag) const
1096 		{
1097 			return mulColSpecialized (w, A, v,
1098 						  typename VectorTraits<Vector1>::VectorCategory (),
1099 						  typename VectorTraits<Vector2>::VectorCategory ());
1100 		}
1101 		template <class Vector1, class Matrix_, class Vector2>
mulSpecialized(Vector1 & w,const Matrix_ & A,const Vector2 & v,MatrixCategories::RowColMatrixTag)1102 		Vector1 &mulSpecialized (Vector1 &w, const Matrix_ &A, const Vector2 &v,
1103 					 MatrixCategories::RowColMatrixTag) const
1104 		{
1105 			return mulRowSpecialized (w, A, v, typename VectorTraits<Vector1>::VectorCategory ());
1106 		}
1107 
1108 		template <class Vector1, class Matrix_, class Vector2>
1109 		Vector1 &axpyinRowSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1110 					       VectorCategories::DenseVectorTag) const;
1111 		template <class Vector1, class Matrix_, class Vector2>
1112 		Vector1 &axpyinRowSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1113 					       VectorCategories::SparseSequenceVectorTag) const;
1114 		template <class Vector1, class Matrix_, class Vector2>
1115 		Vector1 &axpyinRowSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1116 					       VectorCategories::SparseAssociativeVectorTag) const;
1117 		template <class Vector1, class Matrix_, class Vector2>
1118 		Vector1 &axpyinRowSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1119 					       VectorCategories::SparseParallelVectorTag) const;
1120 
1121 		template <class Vector1, class Matrix_, class Vector2>
1122 		Vector1 &axpyinColSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1123 					       VectorCategories::DenseVectorTag) const;
1124 		template <class Vector1, class Matrix_, class Vector2>
1125 		Vector1 &axpyinColSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1126 					       VectorCategories::SparseSequenceVectorTag) const;
1127 		template <class Vector1, class Matrix_, class Vector2>
1128 		Vector1 &axpyinColSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1129 					       VectorCategories::SparseAssociativeVectorTag) const;
1130 		template <class Vector1, class Matrix_, class Vector2>
1131 		Vector1 &axpyinColSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1132 					       VectorCategories::SparseParallelVectorTag) const;
1133 
1134 		template <class Vector1, class Matrix_, class Vector2>
axpyinSpecialized(Vector1 & y,const Matrix_ & A,const Vector2 & x,MatrixCategories::RowMatrixTag)1135 		Vector1 &axpyinSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1136 					    MatrixCategories::RowMatrixTag) const
1137 		{
1138 			return axpyinRowSpecialized (y, A, x, typename VectorTraits<Vector1>::VectorCategory ());
1139 		}
1140 		template <class Vector1, class Matrix_, class Vector2>
axpyinSpecialized(Vector1 & y,const Matrix_ & A,const Vector2 & x,MatrixCategories::ColMatrixTag)1141 		Vector1 &axpyinSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1142 					    MatrixCategories::ColMatrixTag) const
1143 		{
1144 			return axpyinColSpecialized (y, A, x, typename VectorTraits<Vector1>::VectorCategory ());
1145 		}
1146 		template <class Vector1, class Matrix_, class Vector2>
axpyinSpecialized(Vector1 & y,const Matrix_ & A,const Vector2 & x,MatrixCategories::RowColMatrixTag)1147 		Vector1 &axpyinSpecialized (Vector1 &y, const Matrix_ &A, const Vector2 &x,
1148 					    MatrixCategories::RowColMatrixTag) const
1149 		{
1150 			return axpyinRowSpecialized (y, A, x, typename VectorTraits<Vector1>::VectorCategory ());
1151 		}
1152 
1153 		template <class Matrix_, class Iterator>
1154 		inline Matrix_ &permuteRowsByRow (Matrix_   &A,
1155 						 Iterator  P_start,
1156 						 Iterator  P_end) const;
1157 
1158 		template <class Matrix_, class Iterator>
1159 		inline Matrix_ &permuteRowsByCol (Matrix_   &A,
1160 						 Iterator  P_start,
1161 						 Iterator  P_end) const;
1162 
1163 		template <class Matrix_, class Iterator>
permuteRowsSpecialized(Matrix_ & A,Iterator P_start,Iterator P_end,MatrixCategories::RowColMatrixTag)1164 		inline Matrix_ &permuteRowsSpecialized (Matrix_   &A,
1165 						       Iterator  P_start,
1166 						       Iterator  P_end,
1167 						       MatrixCategories::RowColMatrixTag) const
1168 		{
1169 			return permuteRowsByCol (A, P_start, P_end);
1170 		}
1171 
1172 		template <class Matrix_, class Iterator>
permuteRowsSpecialized(Matrix_ & A,Iterator P_start,Iterator P_end,MatrixCategories::RowMatrixTag)1173 		inline Matrix_ &permuteRowsSpecialized (Matrix_   &A,
1174 						       Iterator  P_start,
1175 						       Iterator  P_end,
1176 						       MatrixCategories::RowMatrixTag) const
1177 		{
1178 			return permuteRowsByRow (A, P_start, P_end);
1179 		}
1180 
1181 		template <class Matrix_, class Iterator>
permuteRowsSpecialized(Matrix_ & A,Iterator P_start,Iterator P_end,MatrixCategories::ColMatrixTag)1182 		inline Matrix_ &permuteRowsSpecialized (Matrix_   &A,
1183 						       Iterator  P_start,
1184 						       Iterator  P_end,
1185 						       MatrixCategories::ColMatrixTag) const
1186 		{
1187 			return permuteRowsByCol (A, P_start, P_end);
1188 		}
1189 
1190 		template <class Matrix_, class Iterator>
1191 		inline Matrix_ &permuteColsByRow (Matrix_   &A,
1192 						 Iterator  P_start,
1193 						 Iterator  P_end) const;
1194 
1195 		template <class Matrix_, class Iterator>
1196 		inline Matrix_ &permuteColsByCol (Matrix_   &A,
1197 						 Iterator  P_start,
1198 						 Iterator  P_end) const;
1199 
1200 		template <class Matrix_, class Iterator>
permuteColsSpecialized(Matrix_ & A,Iterator P_start,Iterator P_end,MatrixCategories::RowColMatrixTag)1201 		inline Matrix_ &permuteColsSpecialized (Matrix_   &A,
1202 						       Iterator  P_start,
1203 						       Iterator  P_end,
1204 						       MatrixCategories::RowColMatrixTag) const
1205 		{
1206 			return permuteColsByRow (A, P_start, P_end);
1207 		}
1208 
1209 		template <class Matrix_, class Iterator>
permuteColsSpecialized(Matrix_ & A,Iterator P_start,Iterator P_end,MatrixCategories::RowMatrixTag)1210 		inline Matrix_ &permuteColsSpecialized (Matrix_   &A,
1211 						       Iterator  P_start,
1212 						       Iterator  P_end,
1213 						       MatrixCategories::RowMatrixTag) const
1214 		{
1215 			return permuteColsByRow (A, P_start, P_end);
1216 		}
1217 
1218 		template <class Matrix_, class Iterator>
permuteColsSpecialized(Matrix_ & A,Iterator P_start,Iterator P_end,MatrixCategories::ColMatrixTag)1219 		inline Matrix_ &permuteColsSpecialized (Matrix_   &A,
1220 						       Iterator  P_start,
1221 						       Iterator  P_end,
1222 						       MatrixCategories::ColMatrixTag) const
1223 		{
1224 			return permuteColsByCol (A, P_start, P_end);
1225 		}
1226 
1227 		const Field         *_field;
1228 		VectorDomain<Field>  _VD;
1229 	}; //MatrixDomain
1230 
1231 }
1232 
1233 #include "linbox/matrix/matrixdomain/matrix-domain.inl"
1234 
1235 #endif // __LINBOX_matrix_domain_H
1236 
1237 // Local Variables:
1238 // mode: C++
1239 // tab-width: 4
1240 // indent-tabs-mode: nil
1241 // c-basic-offset: 4
1242 // End:
1243 // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
1244