Functions_Matrix.cxx
1 // Copyright (C) 2001-2011 Vivien Mallet
2 // Copyright (C) 2003-2011 Marc DuruflĂ©
3 // Copyright (C) 2010 INRIA
4 // Author(s): Marc Fragu
5 //
6 // This file is part of the linear-algebra library Seldon,
7 // http://seldon.sourceforge.net/.
8 //
9 // Seldon is free software; you can redistribute it and/or modify it under the
10 // terms of the GNU Lesser General Public License as published by the Free
11 // Software Foundation; either version 2.1 of the License, or (at your option)
12 // any later version.
13 //
14 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
15 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17 // more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with Seldon. If not, see http://www.gnu.org/licenses/.
21 
22 
23 #ifndef SELDON_FILE_FUNCTIONS_MATRIX_CXX
24 #define SELDON_FILE_FUNCTIONS_MATRIX_CXX
25 
26 
27 #include "Functions_Matrix.hxx"
28 
29 
30 /*
31  Function defined in this file:
32 
33  alpha A -> A
34  Mlt(alpha, A)
35 
36  A B -> C
37  Mlt(A, B, C)
38 
39  alpha A B -> C
40  Mlt(alpha, A, B, C)
41 
42  alpha A B + beta C -> C
43  MltAdd(alpha, A, B, beta, C)
44 
45  alpha A + B -> B
46  Add(alpha, A, B)
47 
48  LU factorization of matrix A without pivoting.
49  GetLU(A)
50 
51  Highest absolute value of A.
52  MaxAbs(A)
53 
54  1-norm of matrix A.
55  Norm1(A)
56 
57  infinity norm of matrix A.
58  NormInf(A)
59 
60  transpose of matrix A
61  Transpose(A)
62 
63  B = transpose(A)
64  Transpose(A, B)
65 
66  conjugate of transpose of matrix A
67  TransposeConj(A)
68 
69  conjugate of matrix A
70  Conjugate(A)
71 
72 */
73 
74 
75 namespace Seldon
76 {
77 
78 
80  // MLT //
81 
82 
84 
88  template <class T0,
89  class T1, class Prop1, class Storage1, class Allocator1>
90  void MltScalar(const T0& alpha,
92  {
94  data = A.GetData();
95 
96  long taille = A.GetDataSize();
97  for (long i = 0; i < taille; i++)
98  data[i] *= alpha;
99  }
100 
101 
103 
107  template <class T0,
108  class T1, class Prop1, class Allocator1>
109  void MltScalar(const T0& alpha,
111  {
112  typename T1::value_type alpha_ = alpha;
113  for (int i = 0; i < A.GetMmatrix(); i++)
114  for (int j = 0; j < A.GetNmatrix(); j++)
115  Mlt(alpha, A.GetMatrix(i, j));
116  }
117 
118 
120 
124  template <class T0,
125  class T1, class Prop1, class Allocator1>
126  void MltScalar(const T0& alpha,
128  {
129  typename T1::value_type alpha_ = alpha;
130  for (int i = 0; i < A.GetMmatrix(); i++)
131  for (int j = 0; j < A.GetNmatrix(); j++)
132  Mlt(alpha_, A.GetMatrix(i, j));
133  }
134 
135 
137 
141  template <class T0, class Allocator>
142  void MltScalar(const T0& alpha,
144  {
146  ::float_dense_m m0;
148  ::float_sparse_m m1;
150  ::double_dense_m m2;
152  ::double_sparse_m m3;
153 
154  for (int i = 0; i < A.GetMmatrix(); i++)
155  for (int j = 0; j < A.GetNmatrix(); j++)
156  {
157  switch (A.GetType(i, j))
158  {
159  case 0:
160  A.GetMatrix(i, j, m0);
161  Mlt(float(alpha), m0);
162  A.SetMatrix(i, j, m0);
163  m0.Nullify();
164  break;
165  case 1:
166  A.GetMatrix(i, j, m1);
167  Mlt(float(alpha), m1);
168  A.SetMatrix(i, j, m1);
169  m1.Nullify();
170  break;
171  case 2:
172  A.GetMatrix(i, j, m2);
173  Mlt(double(alpha), m2);
174  A.SetMatrix(i, j, m2);
175  m2.Nullify();
176  break;
177  case 3:
178  A.GetMatrix(i, j, m3);
179  Mlt(double(alpha), m3);
180  A.SetMatrix(i, j, m3);
181  m3.Nullify();
182  break;
183  default:
184  throw WrongArgument("Mlt(alpha, Matrix<FloatDouble, "
185  "DenseSparseCollection)",
186  "Underlying matrix (" + to_str(i) + " ,"
187  + to_str(j) + " ) not defined.");
188  }
189  }
190  }
191 
192 
194 
204  template <class T0, class Prop0, class Allocator0,
205  class T1, class Prop1, class Allocator1,
206  class T2, class Prop2, class Allocator2>
210  {
211 #ifdef SELDON_CHECK_DIMENSIONS
212  CheckDim(A, B, "Mlt(const Matrix<RowSparse>& A, const "
213  "Matrix<RowSparse>& B, Matrix<RowSparse>& C)");
214 #endif
215 
216 #ifdef SELDON_CHECK_MEMORY
217  if (!Allocator2::KeepDataReallocate)
218  throw Undefined("Mlt(RowSparse)", "Function not defined for"
219  " NewAlloc allocator");
220 #endif
221 
222  int h, i, col; long k, l;
223  long Nnonzero; int Nnonzero_row, Nnonzero_row_max;
224  Vector<int> column_index;
225 
226  typedef typename SeldonDefaultAllocator<VectFull, int>::allocator AllocInt;
227  typedef typename SeldonDefaultAllocator<VectFull, long>::allocator AllocLong;
229  T1 value;
230  int m = A.GetM();
231 
232  long* c_ptr = NULL;
233  int* c_ind = NULL;
234  T2* c_data = NULL;
235  C.Clear();
236 
237 #ifdef SELDON_CHECK_MEMORY
238  try
239  {
240 #endif
241 
242  c_ptr = AllocLong::allocate(m + 1);
243 
244 #ifdef SELDON_CHECK_MEMORY
245  }
246  catch (...)
247  {
248  c_ptr = NULL;
249  }
250 
251  if (c_ptr == NULL)
252  throw NoMemory("Mlt(const Matrix<RowSparse>& A, const "
253  "Matrix<RowSparse>& B, Matrix<RowSparse>& C)",
254  "Unable to allocate memory for an array of "
255  + to_str(m + 1) + " integers.");
256 #endif
257 
258  c_ptr[0] = 0;
259 
260  // Number of non-zero elements in C.
261  Nnonzero = 0;
262  for (i = 0; i < m; i++)
263  {
264  c_ptr[i + 1] = c_ptr[i];
265 
266  if (A.GetPtr()[i + 1] != A.GetPtr()[i])
267  // There are elements in the i-th row of A, so there can be non-zero
268  // entries in C as well. Checks whether any column in B has an
269  // element whose row index matches a column index of a non-zero in
270  // the i-th row of A.
271  {
272  // Maximum number of non-zero entry on the i-th row of C.
273  Nnonzero_row_max = 0;
274  // For every element in the i-th row.
275  for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++)
276  {
277  col = A.GetInd()[k];
278  Nnonzero_row_max += B.GetPtr()[col + 1] - B.GetPtr()[col];
279  }
280  // Now gets the column indexes.
281  column_index.Reallocate(Nnonzero_row_max);
282  row_value.Reallocate(Nnonzero_row_max);
283  h = 0;
284  // For every element in the i-th row.
285  for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++)
286  {
287  // The k-th column index (among the nonzero entries) on the
288  // i-th row, and the corresponding value.
289  col = A.GetInd()[k];
290  value = A.GetData()[k];
291  // Loop on all elements in the col-th row in B. These elements
292  // are multiplied with the element (i, col) of A.
293  for (l = B.GetPtr()[col]; l < B.GetPtr()[col + 1]; l++)
294  {
295  column_index(h) = B.GetInd()[l];
296  row_value(h) = value * B.GetData()[l];
297  h++;
298  }
299  }
300  // Now gathers and sorts all elements on the i-th row of C.
301  Nnonzero_row = column_index.GetLength();
302  Assemble(Nnonzero_row, column_index, row_value);
303 
304 #ifdef SELDON_CHECK_MEMORY
305  try
306  {
307 #endif
308 
309  // Reallocates 'c_ind' and 'c_data' in order to append the
310  // elements of the i-th row of C.
311  c_ind =
312  reinterpret_cast<int*>(AllocInt::
313  reallocate(c_ind, Nnonzero + Nnonzero_row));
314 
315  c_data =
316  reinterpret_cast<T2*>(Allocator2::
317  reallocate(c_data, Nnonzero + Nnonzero_row));
318 
319 #ifdef SELDON_CHECK_MEMORY
320  }
321  catch (...)
322  {
323  c_ind = NULL;
324  c_data = NULL;
325  }
326 
327  if ((c_ind == NULL || c_data == NULL)
328  && Nnonzero + Nnonzero_row != 0)
329  throw NoMemory("Mlt(const Matrix<RowSparse>& A, const "
330  "Matrix<RowSparse>& B, Matrix<RowSparse>& C)",
331  "Unable to allocate memory for an array of "
332  + to_str(Nnonzero + Nnonzero_row) + " integers "
333  "and for an array of "
334  + to_str(sizeof(T2) * (Nnonzero + Nnonzero_row))
335  + " bytes.");
336 #endif
337 
338  c_ptr[i + 1] += Nnonzero_row;
339  for (h = 0; h < Nnonzero_row; h++)
340  {
341  c_ind[Nnonzero + h] = column_index(h);
342  c_data[Nnonzero + h] = row_value(h);
343  }
344  Nnonzero += Nnonzero_row;
345  }
346  }
347 
348  C.SetData(A.GetM(), B.GetN(), Nnonzero, c_data, c_ptr, c_ind);
349  }
350 
351 
353 
361  template <class T0, class Prop0, class Allocator0,
362  class T1, class Prop1, class Allocator1,
363  class T2, class Prop2, class Allocator2>
367  {
368 #ifdef SELDON_CHECK_DIMENSIONS
369  CheckDim(A, B, "Mlt(const Matrix<RowMajor>& A, const "
370  "Matrix<RowSparse>& B, Matrix<RowMajor>& C)");
371 #endif
372 
373  int m = A.GetM();
374  int n = A.GetN();
375 
376  C.Reallocate(A.GetM(), B.GetN());
377  C.Zero();
378 
379  for (int i = 0; i < m; i++)
380  {
381  for (int k = 0; k < n; k++)
382  {
383  // Loop on all elements in the k-th row in B. These elements
384  // are multiplied with the element (i, k) of A.
385  for (long l = B.GetPtr()[k]; l < B.GetPtr()[k + 1]; l++)
386  C(i, B.GetInd()[l]) += A(i, k) * B.GetData()[l];
387  }
388  }
389  }
390 
391 
393 
401  template <class T0, class Prop0, class Allocator0,
402  class T1, class Prop1, class Allocator1,
403  class T2, class Prop2, class Allocator2>
406  const class_SeldonTrans&,
409  {
410 #ifdef SELDON_CHECK_DIMENSIONS
411  CheckDim(SeldonNoTrans, A, SeldonTrans, B,
412  "Mlt(const Matrix<RowMajor>& A, const "
413  "Matrix<RowSparse>& B, Matrix<RowMajor>& C)");
414 #endif
415 
416  int m = A.GetM();
417  C.Reallocate(A.GetM(), B.GetM());
418  C.Zero();
419  for (int i = 0; i < m; i++)
420  {
421  for (int j = 0; j < B.GetM(); j++)
422  {
423  // Loop on all elements in the i-th row in B. These elements
424  // are multiplied with the element (i, k) of A.
425  for (long l = B.GetPtr()[j]; l < B.GetPtr()[j + 1]; l++)
426  C(i, j) += A(i, B.GetInd()[l]) * B.GetData()[l];
427  }
428  }
429  }
430 
431 
433 
443  template <class T0, class Prop0, class Allocator0,
444  class T1, class Prop1, class Allocator1,
445  class T2, class Prop2, class Allocator2>
448  const class_SeldonTrans&,
451  {
452 #ifdef SELDON_CHECK_DIMENSIONS
453  CheckDim(SeldonNoTrans, A, SeldonTrans, B,
454  "Mlt(const Matrix<RowSparse>& A, "
455  "const Matrix<RowSparse>& B, Matrix<RowSparse>& C)");
456 #endif
457 
458 #ifdef SELDON_CHECK_MEMORY
459  if (!Allocator2::KeepDataReallocate)
460  throw Undefined("Mlt(RowSparse)", "Function not defined for"
461  " NewAlloc allocator");
462 #endif
463 
464  int h, i, col, ib; long k, kb;
465  int Nnonzero_row;
466  long Nnonzero;
467 
468  Vector<int> column_index;
469  typedef typename SeldonDefaultAllocator<VectFull, int>::allocator AllocInt;
470  typedef typename SeldonDefaultAllocator<VectFull, long>::allocator AllocLong;
472  T2 value;
473 
474  int m = A.GetM();
475  int n = B.GetM();
476 
477  long* c_ptr = NULL;
478  int* c_ind = NULL;
479  T2* c_data = NULL;
480 
481 #ifdef SELDON_CHECK_MEMORY
482  try
483  {
484 #endif
485 
486  c_ptr = AllocLong::allocate(m + 1);
487 
488 #ifdef SELDON_CHECK_MEMORY
489  }
490  catch (...)
491  {
492  c_ptr = NULL;
493  }
494 
495  if (c_ptr == NULL)
496  throw NoMemory("MltNoTransTrans(const Matrix<RowSparse>& A, "
497  "const Matrix<RowSparse>& B, Matrix<RowSparse>& C)",
498  "Unable to allocate memory for an array of "
499  + to_str(m + 1) + " integers.");
500 #endif
501 
502  c_ptr[0] = 0;
503 
504  // Number of non-zero elements in C.
505  Nnonzero = 0;
506  T2 zero;
507  SetComplexZero(zero);
508  value = zero;
509  for (i = 0; i < m; i++)
510  {
511  c_ptr[i + 1] = c_ptr[i];
512 
513  if (A.GetPtr()[i + 1] != A.GetPtr()[i])
514  // There are elements in the i-th row of A, so there can be non-zero
515  // entries in C as well. It is checked below whether any row in B
516  // has an element whose row index matches a column index of a
517  // non-zero in the i-th row of A.
518  {
519  // For every element in the i-th row.
520  for (k = A.GetPtr()[i]; k < A.GetPtr()[i + 1]; k++)
521  {
522  col = A.GetInd()[k];
523  // For every row in B.
524  for (ib = 0; ib < n; ib++)
525  {
526  for (kb = B.GetPtr()[ib]; kb < B.GetPtr()[ib + 1]; kb++)
527  if (col == B.GetInd()[kb])
528  value += A.GetData()[k] * B.GetData()[kb];
529  if (value != zero)
530  {
531  row_value.Append(value);
532  column_index.Append(ib);
533  value = zero;
534  }
535  }
536  }
537 
538  Nnonzero_row = column_index.GetLength();
539  Assemble(Nnonzero_row, column_index, row_value);
540 
541 #ifdef SELDON_CHECK_MEMORY
542  try
543  {
544 #endif
545 
546  // Reallocates 'c_ind' and 'c_data' in order to append the
547  // elements of the i-th row of C.
548  c_ind =
549  reinterpret_cast<int*>(AllocInt::
550  reallocate(c_ind, Nnonzero + Nnonzero_row));
551 
552  c_data =
553  reinterpret_cast<T2*>(Allocator2::
554  reallocate(c_data, Nnonzero + Nnonzero_row));
555 
556 #ifdef SELDON_CHECK_MEMORY
557  }
558  catch (...)
559  {
560  c_ind = NULL;
561  c_data = NULL;
562  }
563 
564  if ((c_ind == NULL || c_data == NULL)
565  && Nnonzero_row != 0)
566  throw NoMemory("MltNoTransTrans(const Matrix<RowSparse>& A, "
567  "const Matrix<RowSparse>& B, "
568  "Matrix<RowSparse>& C)",
569  "Unable to allocate memory for an array of "
570  + to_str(Nnonzero + Nnonzero_row) + " integers "
571  "and for an array of "
572  + to_str(sizeof(T2) * (Nnonzero + Nnonzero_row))
573  + " bytes.");
574 #endif
575 
576  c_ptr[i + 1] += Nnonzero_row;
577  for (h = 0; h < Nnonzero_row; h++)
578  {
579  c_ind[Nnonzero + h] = column_index(h);
580  c_data[Nnonzero + h] = row_value(h);
581  }
582  Nnonzero += Nnonzero_row;
583  }
584 
585  column_index.Clear();
586  row_value.Clear();
587  }
588 
589  C.SetData(A.GetM(), B.GetM(), Nnonzero, c_data, c_ptr, c_ind);
590  }
591 
592 
593  // MLT //
595 
596 
598  // MLTADD //
599 
600 
602 
612  template <class T0,
613  class T1, class Prop1, class Storage1, class Allocator1,
614  class T2, class Prop2, class Storage2, class Allocator2,
615  class T3,
616  class T4, class Prop4, class Storage4, class Allocator4>
617  void MltAddMatrix(const T0& alpha,
620  const T3& beta,
622  {
623  int na = A.GetN();
624  int mc = C.GetM();
625  int nc = C.GetN();
626 
627 #ifdef SELDON_CHECK_DIMENSIONS
628  CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)");
629 #endif
630 
631  if ( (Storage1::Sparse) || (Storage2::Sparse) || (Storage4::Sparse))
632  throw WrongArgument("MltAdd", "This function is intended to dense"
633  " matrices only and not to sparse matrices");
634 
635  T3 zero_T3;
636  SetComplexZero(zero_T3);
637  T4 temp;
638  T4 zero;
639  SetComplexZero(zero);
640 
641  if (beta != zero_T3)
642  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
643  for (int j = Storage4::GetBeginLoop(i);
644  j < Storage4::GetEndLoop(mc, nc, i); j++)
645  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
646  *= beta;
647  else
648  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
649  for (int j = Storage4::GetBeginLoop(i);
650  j < Storage4::GetEndLoop(mc, nc, i); j++)
651  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j)) = zero;
652 
653  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
654  for (int j = Storage4::GetBeginLoop(i);
655  j < Storage4::GetEndLoop(mc, nc, i); j++)
656  {
657  temp = zero;
658  for (int k = 0; k < na; k++)
659  temp += A(Storage4::GetFirst(i, j), k)
660  * B(k, Storage4::GetSecond(i, j));
661  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
662  += alpha * temp;
663  }
664  }
665 
666 
668 
683  template <class T0,
684  class T1, class Prop1, class Storage1, class Allocator1,
685  class T2, class Prop2, class Storage2, class Allocator2,
686  class T3,
687  class T4, class Prop4, class Storage4, class Allocator4>
688  void MltAddMatrix(const T0& alpha,
689  const SeldonTranspose& TransA,
691  const SeldonTranspose& TransB,
693  const T3& beta,
695  {
696  if ( (Storage1::Sparse) || (Storage2::Sparse) || (Storage4::Sparse))
697  throw WrongArgument("MltAdd", "This function is intended to dense"
698  " matrices only and not to sparse matrices");
699 
700  int ma = A.GetM();
701  int na = A.GetN();
702  int mc = C.GetM();
703  int nc = C.GetN();
704 
705 #ifdef SELDON_CHECK_DIMENSIONS
706  CheckDim(TransA, A, TransB, B, C,
707  "MltAdd(alpha, TransA, A, TransB, B, beta, C)");
708 #endif
709 
710  T3 zero_T3, one_T3;
711  SetComplexZero(zero_T3);
712  SetComplexOne(one_T3);
713  T4 temp;
714  T4 zero, one;
715  SetComplexZero(zero);
716  SetComplexOne(one);
717 
718  // step C = beta C
719  if (beta != zero_T3)
720  {
721  if (beta != one_T3)
722  MltScalar(beta, C);
723  }
724  else
725  C.Zero();
726 
727  if (TransB.NoTrans())
728  {
729  if (TransA.NoTrans())
730  MltAddMatrix(alpha, A, B, one, C);
731  else if (TransA.Trans())
732  {
733  // C = C + alpha A^T B
734  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
735  for (int j = Storage4::GetBeginLoop(i);
736  j < Storage4::GetEndLoop(mc, nc, i); j++)
737  {
738  temp = zero;
739  for (int k = 0; k < ma; k++)
740  temp += A(k, Storage4::GetFirst(i, j))
741  * B(k, Storage4::GetSecond(i, j));
742 
743  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
744  += alpha * temp;
745  }
746  }
747  else
748  {
749  // C = C + alpha A^H B
750  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
751  for (int j = Storage4::GetBeginLoop(i);
752  j < Storage4::GetEndLoop(mc, nc, i); j++)
753  {
754  temp = zero;
755  for (int k = 0; k < ma; k++)
756  temp += conjugate(A(k, Storage4::GetFirst(i, j)))
757  * B(k, Storage4::GetSecond(i, j));
758 
759  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
760  += alpha * temp;
761  }
762  }
763  }
764  else if (TransB.ConjTrans())
765  {
766  if (TransA.NoTrans())
767  {
768  // C = C + alpha A B^H
769  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
770  for (int j = Storage4::GetBeginLoop(i);
771  j < Storage4::GetEndLoop(mc, nc, i); j++)
772  {
773  temp = zero;
774  for (int k = 0; k < na; k++)
775  temp += A(Storage4::GetFirst(i, j), k)
776  * conjugate(B(Storage4::GetSecond(i, j), k));
777 
778  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
779  += alpha * temp;
780  }
781  }
782  else if (TransA.Trans())
783  {
784  // C = C + alpha A^T B^H
785  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
786  for (int j = Storage4::GetBeginLoop(i);
787  j < Storage4::GetEndLoop(mc, nc, i); j++)
788  {
789  temp = zero;
790  for (int k = 0; k < ma; k++)
791  temp += A(k, Storage4::GetFirst(i, j))
792  * conjugate(B(Storage4::GetSecond(i, j), k));
793 
794  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
795  += alpha * temp;
796  }
797  }
798  else
799  {
800  // C = C + alpha A^H B^H
801  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
802  for (int j = Storage4::GetBeginLoop(i);
803  j < Storage4::GetEndLoop(mc, nc, i); j++)
804  {
805  temp = zero;
806  for (int k = 0; k < ma; k++)
807  temp += conjugate(A(k, Storage4::GetFirst(i, j)))
808  * conjugate(B(Storage4::GetSecond(i, j), k));
809 
810  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
811  += alpha * temp;
812  }
813  }
814  }
815  else
816  {
817  if (TransA.NoTrans())
818  {
819  // C = C + alpha A B^T
820  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
821  for (int j = Storage4::GetBeginLoop(i);
822  j < Storage4::GetEndLoop(mc, nc, i); j++)
823  {
824  temp = zero;
825  for (int k = 0; k < na; k++)
826  temp += A(Storage4::GetFirst(i, j), k)
827  * B(Storage4::GetSecond(i, j), k);
828 
829  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
830  += alpha * temp;
831  }
832  }
833  else if (TransA.Trans())
834  {
835  // C = C + alpha A^T B^T
836  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
837  for (int j = Storage4::GetBeginLoop(i);
838  j < Storage4::GetEndLoop(mc, nc, i); j++)
839  {
840  temp = zero;
841  for (int k = 0; k < ma; k++)
842  temp += A(k, Storage4::GetFirst(i, j))
843  * B(Storage4::GetSecond(i, j), k);
844 
845  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
846  += alpha * temp;
847  }
848  }
849  else
850  {
851  // C = C + alpha A^H B^T
852  for (int i = 0; i < Storage4::GetFirst(mc, nc); i++)
853  for (int j = Storage4::GetBeginLoop(i);
854  j < Storage4::GetEndLoop(mc, nc, i); j++)
855  {
856  temp = zero;
857  for (int k = 0; k < ma; k++)
858  temp += conjugate(A(k, Storage4::GetFirst(i, j)))
859  * B(Storage4::GetSecond(i, j), k);
860 
861  C.Get(Storage4::GetFirst(i, j), Storage4::GetSecond(i, j))
862  += alpha * temp;
863  }
864  }
865  }
866  }
867 
868 
870 
880  template <class T0,
881  class T1, class Prop1, class Allocator1,
882  class T2, class Allocator2,
883  class T3,
884  class T4, class Prop4, class Allocator4>
885  void MltAddMatrix(const T0& alpha,
888  const T3& beta,
890  {
891  int na = A.GetN();
892  int nc = C.GetN();
893 
894 #ifdef SELDON_CHECK_DIMENSIONS
895  CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)");
896 #endif
897  T1 *local_a;
898  MatGetArray(A.GetPetscMatrix(), &local_a);
899  int nlocal_A;
900  int mlocal_A;
901  MatGetLocalSize(A.GetPetscMatrix(), &mlocal_A, &nlocal_A);
903  local_A.SetData(mlocal_A, na, local_a);
904 
905  T4 *local_c;
906  MatGetArray(C.GetPetscMatrix(), &local_c);
907  int nlocal_C;
908  int mlocal_C;
909  MatGetLocalSize(C.GetPetscMatrix(), &mlocal_C, &nlocal_C);
911  local_C.SetData(mlocal_C, nc, local_c);
912 
913  MltAdd(alpha, local_A, B, beta, local_C);
914 
915  local_A.Nullify();
916  MatRestoreArray(A.GetPetscMatrix(), &local_a);
917  A.Flush();
918 
919  local_C.Nullify();
920  MatRestoreArray(C.GetPetscMatrix(), &local_c);
921  C.Flush();
922  }
923 
924 
926 
936  template <class T0,
937  class T1, class Prop1, class Allocator1,
938  class T2, class Prop2, class Allocator2,
939  class T3,
940  class T4, class Prop4, class Allocator4>
941  void MltAddMatrix(const T0& alpha,
944  const T3& beta,
946  {
947  int na = A.GetNmatrix();
948  int mc = C.GetMmatrix();
949  int nc = C.GetNmatrix();
950 
951 #ifdef SELDON_CHECK_DIMENSIONS
952  CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)");
953 #endif
954 
955  typedef typename T4::value_type value_type;
956 
957  MltScalar(value_type(beta), C);
958 
959  for (int i = 0; i < mc; i++ )
960  for (int j = 0; j < nc; j++)
961  for (int k = 0; k < na; k++)
962  MltAdd(value_type(alpha), A.GetMatrix(i, k), B.GetMatrix(k, j),
963  value_type(1), C.GetMatrix(i, j));
964  }
965 
966 
968 
978  template <class T0,
979  class T1, class Prop1, class Allocator1,
980  class T2, class Prop2, class Allocator2,
981  class T3,
982  class T4, class Prop4, class Allocator4>
983  void MltAddMatrix(const T0& alpha,
986  const T3& beta,
988  {
989  int na = A.GetNmatrix();
990  int mc = C.GetMmatrix();
991  int nc = C.GetNmatrix();
992 
993 #ifdef SELDON_CHECK_DIMENSIONS
994  CheckDim(A, B, C, "MltAdd(alpha, A, B, beta, C)");
995 #endif
996 
997  typedef typename T4::value_type value_type;
998 
999  MltScalar(value_type(beta), C);
1000 
1001  for (int i = 0; i < mc; i++ )
1002  for (int j = 0; j < nc; j++)
1003  for (int k = 0; k < na; k++)
1004  MltAdd(value_type(alpha), A.GetMatrix(i, k), B.GetMatrix(k, j),
1005  value_type(1), C.GetMatrix(i, j));
1006  }
1007 
1008 
1009  template <class T0,
1010  class T1, class Allocator1,
1011  class T2, class Allocator2,
1012  class T3,
1013  class T4, class Allocator4>
1014  void MltAddMatrix(const T0& alpha,
1015  const Matrix<T1, General, RowMajor, Allocator1>& A,
1016  const Matrix<T2, General, RowMajor, Allocator2>& B,
1017  const T3& beta,
1018  Matrix<T4, General, RowSparse, Allocator4>& C)
1019  {
1020  throw Undefined("void MltAdd(const T0 alpha,"
1021  "const Matrix<T1, General, RowMajor, Allocator1>& A,"
1022  "const Matrix<T2, General, RowMajor, Allocator2>& B,"
1023  "const T3 beta,"
1024  "Matrix<T4, General, RowSparse, Allocator4>& C)");
1025  }
1026 
1027 
1028  template <class T0,
1029  class T1, class Allocator1,
1030  class T2, class Allocator2,
1031  class T3,
1032  class T4, class Allocator4>
1033  void MltAddMatrix(const T0& alpha,
1034  const Matrix<T1, General, RowMajor, Allocator1>& A,
1035  const Matrix<T2, General, RowSparse, Allocator2>& B,
1036  const T3& beta,
1037  Matrix<T4, General, RowSparse, Allocator4>& C)
1038  {
1039  throw Undefined("void MltAdd(const T0 alpha,"
1040  "const Matrix<T1, General, RowMajor, Allocator1>& A,"
1041  "const Matrix<T2, General, RowSparse, Allocator2>& B,"
1042  "const T3 beta,"
1043  "Matrix<T4, General, RowSparse, Allocator4>& C)");
1044  }
1045 
1046 
1047  template <class T0,
1048  class T1, class Allocator1,
1049  class T2, class Allocator2,
1050  class T3,
1051  class T4, class Allocator4>
1052  void MltAddMatrix(const T0& alpha,
1053  const Matrix<T1, General, RowSparse, Allocator1>& A,
1054  const Matrix<T2, General, RowMajor, Allocator2>& B,
1055  const T3& beta,
1056  Matrix<T4, General, RowSparse, Allocator4>& C)
1057  {
1058  throw Undefined("void MltAdd(const T0 alpha,"
1059  "const Matrix<T1, General, RowSparse, Allocator1>& A,"
1060  "const Matrix<T2, General, RowMajor, Allocator2>& B,"
1061  "const T3 beta,"
1062  "Matrix<T4, General, RowSparse, Allocator4>& C)");
1063  }
1064 
1065 
1066  template <class T0,
1067  class Allocator1,
1068  class Allocator2,
1069  class Allocator3,
1070  class T4, class Prop4, class Storage4, class Allocator4>
1071  void MltAdd_heterogeneous(const T0& alpha,
1072  const Matrix<FloatDouble, General,
1073  DenseSparseCollection, Allocator1>& A,
1074  const Matrix<FloatDouble, General,
1075  DenseSparseCollection, Allocator2>& B,
1076  Matrix<FloatDouble, General,
1077  DenseSparseCollection, Allocator3>& C,
1078  Matrix<T4, Prop4, Storage4, Allocator4>& mc,
1079  int i, int j)
1080  {
1081  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
1082  ::float_dense_m m0a;
1083  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
1084  ::float_sparse_m m1a;
1085  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
1086  ::double_dense_m m2a;
1087  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator1>
1088  ::double_sparse_m m3a;
1089 
1090  int na = A.GetNmatrix();
1091  for (int k = 0; k < na; k++)
1092  {
1093  switch (A.GetType(i, k))
1094  {
1095  case 0:
1096  A.GetMatrix(i, k, m0a);
1097  MltAdd_heterogeneous2(alpha, m0a, B, C, mc, j, k);
1098  m0a.Nullify();
1099  break;
1100  case 1:
1101  A.GetMatrix(i, k, m1a);
1102  MltAdd_heterogeneous2(alpha, m1a, B, C, mc, j, k);
1103  m1a.Nullify();
1104  break;
1105  case 2:
1106  A.GetMatrix(i, k, m2a);
1107  MltAdd_heterogeneous2(alpha, m2a, B, C, mc, j, k);
1108  m2a.Nullify();
1109  break;
1110  case 3:
1111  A.GetMatrix(i, k, m3a);
1112  MltAdd_heterogeneous2(alpha, m3a, B, C, mc, j, k);
1113  m3a.Nullify();
1114  break;
1115  default:
1116  throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>::"
1117  "MltAdd_heterogeneous(alpha, A, B, beta, C) ",
1118  "Underlying matrix A (" + to_str(i) + " ,"
1119  + to_str(k) + " ) not defined.");
1120  }
1121  }
1122  }
1123 
1124 
1125  template<class T0,
1126  class T1, class Prop1, class Storage1, class Allocator1,
1127  class Allocator2,
1128  class Allocator3,
1129  class T4, class Prop4, class Storage4, class Allocator4>
1130  void MltAdd_heterogeneous2(const T0& alpha,
1131  const Matrix<T1, Prop1,
1132  Storage1, Allocator1>& ma,
1133  const Matrix<FloatDouble, General,
1134  DenseSparseCollection, Allocator2>& B,
1135  Matrix<FloatDouble, General,
1136  DenseSparseCollection, Allocator3>& C,
1137  Matrix<T4, Prop4, Storage4, Allocator4>& mc,
1138  int j, int k)
1139  {
1140  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1141  ::float_dense_m m0b;
1142  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1143  ::float_sparse_m m1b;
1144  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1145  ::double_dense_m m2b;
1146  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1147  ::double_sparse_m m3b;
1148 
1149  switch (B.GetType(k, j))
1150  {
1151  case 0:
1152  B.GetMatrix(k, j, m0b);
1153  MltAddMatrix(alpha, ma, m0b, 1., mc);
1154  m0b.Nullify();
1155  break;
1156  case 1:
1157  B.GetMatrix(k, j, m1b);
1158  MltAddMatrix(alpha, ma, m1b, 1., mc);
1159  m1b.Nullify();
1160  break;
1161  case 2:
1162  B.GetMatrix(k, j, m2b);
1163  MltAddMatrix(alpha, ma, m2b, 1., mc);
1164  m2b.Nullify();
1165  break;
1166  case 3:
1167  B.GetMatrix(k, j, m3b);
1168  MltAddMatrix(alpha, ma, m3b, 1., mc);
1169  m3b.Nullify();
1170  break;
1171  default:
1172  throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>"
1173  "::MltAdd_heterogeneous2(alpha, A, B, beta, C)",
1174  "Underlying matrix B (" + to_str(k) + " ,"
1175  + to_str(j) + " ) not defined.");
1176  }
1177  }
1178 
1179 
1180 
1182 
1186  template <class T0, class Allocator1, class Allocator2, class T3,
1187  class Allocator4>
1188  void MltAddMatrix(const T0& alpha,
1190  Allocator1>& A,
1192  Allocator2>& B,
1193  const T3& beta,
1195  Allocator4>& C)
1196  {
1198  ::float_dense_m m0c;
1200  ::float_sparse_m m1c;
1202  ::double_dense_m m2c;
1204  ::double_sparse_m m3c;
1205 
1206  MltScalar(beta, C);
1207 
1208  int mc = C.GetMmatrix();
1209  int nc = C.GetNmatrix();
1210  for (int i = 0; i < mc; i++ )
1211  for (int j = 0; j < nc; j++)
1212  {
1213  switch (C.GetType(i, j))
1214  {
1215  case 0:
1216  C.GetMatrix(i, j, m0c);
1217  MltAdd_heterogeneous(float(alpha), A, B, C, m0c, i, j);
1218  C.SetMatrix(i, j, m0c);
1219  m0c.Nullify();
1220  break;
1221  case 1:
1222  C.GetMatrix(i, j, m1c);
1223  MltAdd_heterogeneous(float(alpha), A, B, C, m1c, i, j);
1224  C.SetMatrix(i, j, m1c);
1225  m1c.Nullify();
1226  break;
1227  case 2:
1228  C.GetMatrix(i, j, m2c);
1229  MltAdd_heterogeneous(double(alpha), A, B, C, m2c, i, j);
1230  C.SetMatrix(i, j, m2c);
1231  m2c.Nullify();
1232  break;
1233  case 3:
1234  C.GetMatrix(i, j, m3c);
1235  MltAdd_heterogeneous(double(alpha), A, B, C, m3c, i, j);
1236  C.SetMatrix(i, j, m3c);
1237  m3c.Nullify();
1238  break;
1239  default:
1240  throw WrongArgument("Matrix<FloatDouble, DenseSparseCollection>"
1241  "::MltAdd(alpha, A, B, beta, C) ",
1242  "Underlying matrix C (" + to_str(i) + " ,"
1243  + to_str(j) + " ) not defined.");
1244  }
1245  }
1246  }
1247 
1248 
1250 
1260  template <class T0,
1261  class T1, class Prop1, class Allocator1,
1262  class T2, class Prop2, class Allocator2,
1263  class T3,
1264  class T4, class Prop4, class Allocator4>
1265  void MltAddMatrix(const T0& alpha,
1268  const T3& beta,
1270  {
1271  T0 zero, one;
1272  SetComplexZero(zero);
1273  SetComplexOne(one);
1274  if (beta == zero)
1275  {
1276  if (alpha == zero)
1277  MltScalar(alpha, C);
1278  else
1279  {
1280  MltMatrix(A, B, C);
1281  if (alpha != one)
1282  MltScalar(alpha, C);
1283  }
1284  }
1285  else
1286  {
1287  if (alpha == zero)
1288  MltScalar(beta, C);
1289  else
1290  {
1292  MltMatrix(A, B, tmp);
1293  if (beta != one)
1294  MltScalar(beta, C);
1295 
1296  AddMatrix(alpha, tmp, C);
1297  }
1298  }
1299  }
1300 
1301 
1303 
1319  template <class T0,
1320  class T1, class Prop1, class Allocator1,
1321  class T2, class Prop2, class Allocator2,
1322  class T3,
1323  class T4, class Prop4, class Allocator4>
1324  void MltAddMatrix(const T0& alpha,
1325  const SeldonTranspose& TransA,
1327  const SeldonTranspose& TransB,
1329  const T3& beta,
1331  {
1332  if (!TransA.NoTrans())
1333  throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, "
1334  "const Matrix<RowSparse>& A, SeldonTranspose "
1335  "TransB, const Matrix<RowSparse>& B, T3 beta, "
1336  "Matrix<RowSparse>& C)",
1337  "'TransA' must be equal to 'SeldonNoTrans'.");
1338  if (!TransB.NoTrans() && !TransB.Trans())
1339  throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, "
1340  "const Matrix<RowSparse>& A, SeldonTranspose "
1341  "TransB, const Matrix<RowSparse>& B, T3 beta, "
1342  "Matrix<RowSparse>& C)",
1343  "'TransB' must be equal to 'SeldonNoTrans' or "
1344  "'SeldonTrans'.");
1345 
1346  if (TransB.Trans())
1347  {
1348  T0 zero, one;
1349  SetComplexZero(zero);
1350  SetComplexOne(one);
1351 
1352  if (beta == zero)
1353  {
1354  if (alpha == zero)
1355  MltScalar(alpha, C);
1356  else
1357  {
1358  MltMatrix(SeldonNoTrans, A, SeldonTrans, B, C);
1359  if (alpha != one)
1360  MltScalar(alpha, C);
1361  }
1362  }
1363  else
1364  {
1365  if (alpha == zero)
1366  MltScalar(beta, C);
1367  else
1368  {
1370  MltMatrix(SeldonNoTrans, A, SeldonTrans, B, tmp);
1371  if (beta != one)
1372  MltScalar(beta, C);
1373 
1374  AddMatrix(alpha, tmp, C);
1375  }
1376  }
1377  }
1378  else
1379  MltAddMatrix(alpha, A, B, beta, C);
1380  }
1381 
1382 
1384  template<class T0, class T1, class Prop1, class Allocator1, class T4,
1385  class T2, class Prop2, class Storage2, class Allocator2,
1386  class T3, class Prop3, class Storage3, class Allocator3>
1387  void MltAddMatrix(const T0& alpha,
1390  const T4& beta,
1392  {
1393  if (Storage2::Sparse || Storage3::Sparse)
1394  throw WrongArgument("Mlt", "Function intended for product "
1395  " between a sparse matrix and a dense matrix");
1396 
1397 #ifdef SELDON_CHECK_DIMENSIONS
1398  CheckDim(A, B, C, "Mlt(A, B, C)");
1399 #endif
1400 
1401  long* ptr = A.GetPtr();
1402  int* ind = A.GetInd();
1403  T1* data = A.GetData();
1404  T3 zero, val;
1405  SetComplexZero(zero);
1406 
1407  int m = A.GetM();
1408  int n = B.GetN();
1409  if (beta == zero)
1410  C.Zero();
1411  else
1412  MltScalar(beta, C);
1413 
1414  for (int i = 0; i < m; i++)
1415  for (long k2 = ptr[i]; k2 < ptr[i+1]; k2++)
1416  {
1417  int k = ind[k2];
1418  val = data[k2] * alpha;
1419  // c_ij = \sum_k a_ik b_kj
1420  for (int j = 0; j < n; j++)
1421  C(i, j) += val*B(k, j);
1422  }
1423  }
1424 
1425 
1427  template<class T0, class T1, class Prop1, class Allocator1, class T4,
1428  class T2, class Prop2, class Storage2, class Allocator2,
1429  class T3, class Prop3, class Storage3, class Allocator3>
1430  void MltAddMatrix(const T0& alpha,
1431  const SeldonTranspose& TransA,
1433  const SeldonTranspose& TransB,
1435  const T4& beta,
1437  {
1438  if (Storage2::Sparse || Storage3::Sparse)
1439  throw WrongArgument("Mlt", "Function intended for product "
1440  " between a sparse matrix and a dense matrix");
1441 
1442  long* ptr = A.GetPtr();
1443  int* ind = A.GetInd();
1444  T1* data = A.GetData();
1445  T3 zero, val;
1446  SetComplexZero(zero);
1447 
1448  int m = A.GetM();
1449  int n = B.GetN();
1450 
1451  if (TransA.NoTrans())
1452  {
1453  if (TransB.NoTrans())
1454  MltAddMatrix(alpha, A, B, beta, C);
1455  else if (TransB.Trans())
1456  {
1457 
1458 #ifdef SELDON_CHECK_DIMENSIONS
1459  CheckDim(SeldonNoTrans, A, SeldonTrans, B, C, "MltAdd(A, B, C)");
1460 #endif
1461 
1462  if (beta == zero)
1463  C.Zero();
1464  else
1465  MltScalar(beta, C);
1466 
1467  for (int i = 0; i < m; i++)
1468  for (long k2 = ptr[i]; k2 < ptr[i+1]; k2++)
1469  {
1470  int k = ind[k2];
1471  val = data[k2] * alpha;
1472  // c_ij = \sum_k a_ik b_jk
1473  for (int j = 0; j < B.GetM(); j++)
1474  C(i, j) += val*B(j, k);
1475  }
1476  }
1477  else
1478  throw Undefined("MltAdd", "Not implemented for ConjTrans");
1479  }
1480  else if (TransA.Trans())
1481  {
1482  if (TransB.NoTrans())
1483  {
1484 #ifdef SELDON_CHECK_DIMENSIONS
1485  CheckDim(SeldonTrans, A, SeldonNoTrans, B, C, "MltAdd(A, B, C)");
1486 #endif
1487 
1488  if (beta == zero)
1489  C.Zero();
1490  else
1491  MltScalar(beta, C);
1492 
1493  for (int i = 0; i < m; i++)
1494  for (long k2 = ptr[i]; k2 < ptr[i+1]; k2++)
1495  {
1496  int k = ind[k2];
1497  val = data[k2] * alpha;
1498  // c_kj = \sum_i a_ik b_ij
1499  for (int j = 0; j < n; j++)
1500  C(k, j) += val*B(i, j);
1501  }
1502  }
1503  else if (TransB.Trans())
1504  {
1505 #ifdef SELDON_CHECK_DIMENSIONS
1506  CheckDim(SeldonTrans, A, SeldonTrans, B, C, "MltAdd(A, B, C)");
1507 #endif
1508 
1509  if (beta == zero)
1510  C.Zero();
1511  else
1512  MltScalar(beta, C);
1513 
1514  for (int i = 0; i < m; i++)
1515  for (long k2 = ptr[i]; k2 < ptr[i+1]; k2++)
1516  {
1517  int k = ind[k2];
1518  val = data[k2] * alpha;
1519  // c_kj = \sum_i a_ik b_ji
1520  for (int j = 0; j < B.GetM(); j++)
1521  C(k, j) += val*B(j, i);
1522  }
1523  }
1524  else
1525  throw Undefined("MltAdd", "Not implemented for ConjTrans");
1526  }
1527  else
1528  throw Undefined("MltAdd", "Not implemented for ConjTrans");
1529 
1530  }
1531 
1532 
1542  template <class T0,
1543  class T1, class Prop1, class Allocator1,
1544  class T2, class Prop2, class Allocator2,
1545  class T3,
1546  class T4, class Prop4, class Allocator4>
1547  void MltAddMatrix(const T0& alpha,
1548  const SeldonTranspose& TransA,
1550  const SeldonTranspose& TransB,
1552  const T3& beta,
1554  {
1555  if (!TransA.NoTrans())
1556  throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, "
1557  "const Matrix<RowMajor>& A, SeldonTranspose "
1558  "TransB, const Matrix<RowSparse>& B, T3 beta, "
1559  "Matrix<RowSparse>& C)",
1560  "'TransA' must be equal to 'SeldonNoTrans'.");
1561  if (!TransB.NoTrans() && !TransB.Trans())
1562  throw WrongArgument("MltAdd(T0 alpha, SeldonTranspose TransA, "
1563  "const Matrix<RowMajor>& A, SeldonTranspose "
1564  "TransB, const Matrix<RowSparse>& B, T3 beta, "
1565  "Matrix<RowMajor>& C)",
1566  "'TransB' must be equal to 'SeldonNoTrans' or "
1567  "'SeldonTrans'.");
1568 
1569 #ifdef SELDON_CHECK_DIMENSIONS
1570  CheckDim(SeldonNoTrans, A, SeldonTrans, B, C,
1571  "MltAdd(T0 alpha, const Matrix<RowMajor>& A, const "
1572  "Matrix<RowSparse>& B, T3 beta, Matrix<RowMajor>& C)");
1573 #endif
1574 
1575  if (TransB.Trans())
1576  {
1577  T2 zero;
1578  SetComplexZero(zero);
1579  int m = A.GetM();
1580  if (beta == zero)
1581  C.Zero();
1582  else
1583  MltScalar(beta, C);
1584 
1585  if (alpha != zero)
1586  for (int i = 0; i < m; i++)
1587  for (int j = 0; j < B.GetM(); j++)
1588  {
1589  // Loop on all elements in the i-th row in B. These elements
1590  // are multiplied with the element (i, k) of A.
1591  for (long l = B.GetPtr()[j]; l < B.GetPtr()[j + 1]; l++)
1592  C(i, j) += alpha * A(i, B.GetInd()[l]) * B.GetData()[l];
1593  }
1594  }
1595  else
1596  MltAddMatrix(alpha, A, B, beta, C);
1597  }
1598 
1599 
1600  // MLTADD //
1602 
1603 
1604 
1606  // ADD //
1607 
1608 
1610 
1617  template<class T0, class T1, class Prop1, class Storage1, class Allocator1,
1618  class T2, class Prop2, class Storage2, class Allocator2>
1619  void AddMatrix(const T0& alpha,
1622  {
1623  if ( (Storage1::Sparse) || (Storage2::Sparse) )
1624  throw WrongArgument("Add", "This function is intended to dense"
1625  " matrices only and not to sparse matrices");
1626 
1627  int i, j;
1628  int mb = B.GetM(), nb = B.GetN();
1629  for (i = 0; i < Storage2::GetFirst(mb, nb); i++)
1630  for (j = Storage2::GetBeginLoop(i);
1631  j < Storage2::GetEndLoop(mb, nb, i); j++)
1632  B.Get(Storage2::GetFirst(i, j), Storage2::GetSecond(i, j))
1633  += alpha * A(Storage2::GetFirst(i, j), Storage2::GetSecond(i, j));
1634  }
1635 
1636 
1638 
1645  template<class T0,
1646  class T1, class Prop1, class Allocator1,
1647  class T2, class Prop2, class Allocator2>
1648  void AddMatrix(const T0& alpha,
1651  {
1652  int na = A.GetNmatrix();
1653  int ma = A.GetMmatrix();
1654 
1655  typedef typename T2::value_type value_type;
1656 
1657  for (int i = 0; i < ma; i++ )
1658  for (int j = 0; j < na; j++)
1659  Add(value_type(alpha), A.GetMatrix(i, j), B.GetMatrix(i, j));
1660  }
1661 
1662 
1664 
1671  template<class T0,
1672  class T1, class Prop1, class Allocator1,
1673  class T2, class Prop2, class Allocator2>
1674  void AddMatrix(const T0& alpha,
1677  {
1678  int na = A.GetNmatrix();
1679  int ma = A.GetMmatrix();
1680 
1681  typedef typename T2::value_type value_type;
1682 
1683  for (int i = 0; i < ma; i++ )
1684  for (int j = 0; j < na; j++)
1685  Add(value_type(alpha), A.GetMatrix(i, j), B.GetMatrix(i, j));
1686  }
1687 
1688 
1689  template <class T0,
1690  class T1, class Prop1, class Storage1, class Allocator1,
1691  class Allocator2>
1692  void Add_heterogeneous(const T0& alpha,
1693  const Matrix<T1, Prop1, Storage1, Allocator1 >& ma,
1694  Matrix<FloatDouble, General,
1695  DenseSparseCollection, Allocator2>& B,
1696  int i, int j)
1697  {
1698  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1699  ::float_dense_m m0b;
1700  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1701  ::float_sparse_m m1b;
1702  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1703  ::double_dense_m m2b;
1704  typename Matrix<FloatDouble, General, DenseSparseCollection, Allocator2>
1705  ::double_sparse_m m3b;
1706 
1707  T0 alpha_ = alpha;
1708 
1709  switch (B.GetType(i, j))
1710  {
1711  case 0:
1712  B.GetMatrix(i, j, m0b);
1713  Add(float(alpha_), ma, m0b);
1714  B.SetMatrix(i, j, m0b);
1715  m0b.Nullify();
1716  break;
1717  case 1:
1718  B.GetMatrix(i, j, m1b);
1719  Add(float(alpha_), ma, m1b);
1720  B.SetMatrix(i, j, m1b);
1721  m1b.Nullify();
1722  break;
1723  case 2:
1724  B.GetMatrix(i, j, m2b);
1725  Add(double(alpha_), ma, m2b);
1726  B.SetMatrix(i, j, m2b);
1727  m2b.Nullify();
1728  break;
1729  case 3:
1730  B.GetMatrix(i, j, m3b);
1731  Add(double(alpha_), ma, m3b);
1732  B.SetMatrix(i, j, m3b);
1733  m3b.Nullify();
1734  break;
1735  default:
1736  throw WrongArgument("Add_heterogeneous(alpha, Matrix<FloatDouble, "
1737  "DenseSparseCollection>, Matrix<FloatDouble,"
1738  "DenseSparseCollection> )",
1739  "Underlying matrix (" + to_str(i) + " ,"
1740  + to_str(j) + " ) not defined.");
1741  }
1742  }
1743 
1744 
1746 
1750  template <class T0, class Allocator1, class Allocator2>
1751  void AddMatrix(const T0& alpha,
1752  const Matrix<FloatDouble, General,
1753  DenseSparseCollection, Allocator1>& A,
1755  {
1757  ::float_dense_m m0a;
1759  ::float_sparse_m m1a;
1761  ::double_dense_m m2a;
1763  ::double_sparse_m m3a;
1764 
1765  T0 alpha_ = alpha;
1766 
1767  for (int i = 0; i < B.GetMmatrix(); i++)
1768  for (int j = 0; j < B.GetNmatrix(); j++)
1769  {
1770  switch (B.GetType(i, j))
1771  {
1772  case 0:
1773  A.GetMatrix(i, j, m0a);
1774  Add_heterogeneous(float(alpha_), m0a, B, i, j);
1775  m0a.Nullify();
1776  break;
1777  case 1:
1778  A.GetMatrix(i, j, m1a);
1779  Add_heterogeneous(float(alpha_), m1a, B, i, j);
1780  m1a.Nullify();
1781  break;
1782  case 2:
1783  A.GetMatrix(i, j, m2a);
1784  Add_heterogeneous(double(alpha_), m2a, B, i, j);
1785  m2a.Nullify();
1786  break;
1787  case 3:
1788  A.GetMatrix(i, j, m3a);
1789  Add_heterogeneous(double(alpha_), m3a, B, i, j);
1790  m3a.Nullify();
1791  break;
1792  default:
1793  throw
1794  WrongArgument("Add(alpha, Matrix<FloatDouble, "
1795  "DenseSparseCollection>, Matrix<FloatDouble,"
1796  "DenseSparseCollection> )",
1797  "Underlying matrix (" + to_str(i) + " ,"
1798  + to_str(j) + " ) not defined.");
1799  }
1800  }
1801  }
1802 
1803 
1804  template<class T0, class T1, class Prop1, class Allocator1,
1805  class T2, class Prop2, class Allocator2>
1806  void AddMatrix(const T0& alpha,
1807  const Matrix<T1, Prop1, RowMajor, Allocator1>& A,
1808  Matrix<T2, Prop2, RowSparse, Allocator2>& B)
1809  {
1810  throw Undefined("void Add(const T0& alpha,"
1811  "const Matrix<T1, Prop1, RowMajor, Allocator1>& A,"
1812  "Matrix<T2, Prop2, RowSparse, Allocator2>& B)");
1813  }
1814 
1815 
1816  template<class T0, class T1, class Prop1, class Allocator1,
1817  class T2, class Prop2, class Allocator2>
1818  void AddMatrix(const T0& alpha,
1819  const Matrix<T1, Prop1, ColMajor, Allocator1>& A,
1820  Matrix<T2, Prop2, RowSparse, Allocator2>& B)
1821  {
1822  throw Undefined("void Add(const T0& alpha,"
1823  "const Matrix<T1, Prop1, RowMajor, Allocator1>& A,"
1824  "Matrix<T2, Prop2, RowSparse, Allocator2>& B)");
1825  }
1826 
1827 
1828  template<class T0, class T1, class Prop1, class Allocator1,
1829  class T2, class Prop2, class Storage, class Allocator2>
1830  void Add_csr(const T0& alpha,
1831  const Matrix<T1, Prop1, Storage, Allocator1>& A,
1832  Matrix<T2, Prop2, Storage, Allocator2>& B, int p)
1833  {
1834 #ifdef SELDON_CHECK_BOUNDS
1835  if (A.GetM() != B.GetM() || A.GetN() != B.GetN())
1836  throw WrongDim("Add(alpha, const Matrix<RowSparse>& A, "
1837  "Matrix<RowSparse>& B)",
1838  "Unable to add a " + to_str(A.GetM()) + " x "
1839  + to_str(A.GetN()) + " matrix with a "
1840  + to_str(B.GetM()) + " x " + to_str(B.GetN())
1841  + " matrix.");
1842 #endif
1843 
1844  int i = 0;
1845  long j = 0;
1846  long k;
1847 
1848  if (A.GetNonZeros() == B.GetNonZeros())
1849  // A and B might have the same structure.
1850  {
1851  // Loop over all non-zeros. If the structures of A and B differ at any
1852  // time, the loop is broken and a different strategy is undertaken.
1853  for (i = 0; i < p; i++)
1854  if (A.GetPtr()[i + 1] == B.GetPtr()[i + 1])
1855  {
1856  for (j = A.GetPtr()[i]; j < A.GetPtr()[i + 1]; j++)
1857  if (A.GetInd()[j] == B.GetInd()[j])
1858  B.GetData()[j] += alpha * A.GetData()[j];
1859  else
1860  break;
1861  if (j != A.GetPtr()[i + 1])
1862  break;
1863  }
1864  else
1865  break;
1866  // Success: A and B have the same structure.
1867  if (i == A.GetM())
1868  return;
1869  }
1870 
1871  // The addition is performed row by row in the following lines. Thus the
1872  // additions already performed in the current line, if started, should be
1873  // canceled.
1874  for (k = A.GetPtr()[i]; k < j; k++)
1875  if (A.GetInd()[k] == B.GetInd()[k])
1876  B.GetData()[k] -= alpha * A.GetData()[k];
1877 
1878  // Number of non zero entries currently found.
1879  long Nnonzero = A.GetPtr()[i];
1880 
1881  // counting the number of non-zero entries
1882  long kb, jb(0), ka, ja(0);
1883  for (int i2 = i; i2 < p; i2++)
1884  {
1885  kb = B.GetPtr()[i2];
1886 
1887  for (ka = A.GetPtr()[i2]; ka < A.GetPtr()[i2 + 1]; ka++)
1888  {
1889  ja = A.GetInd()[ka];
1890  while (kb < B.GetPtr()[i2 + 1] && B.GetInd()[kb] < ja)
1891  {
1892  kb++;
1893  Nnonzero++;
1894  }
1895 
1896  if (kb < B.GetPtr()[i2 + 1] && ja == B.GetInd()[kb])
1897  kb++;
1898 
1899  Nnonzero++;
1900  }
1901 
1902  while (kb < B.GetPtr()[i2 + 1])
1903  {
1904  kb++;
1905  Nnonzero++;
1906  }
1907  }
1908 
1909  // A and B do not have the same structure. An intermediate matrix will be
1910  // needed. The first i rows have already been added. These computations
1911  // are preserved in arrays Ptr, Ind Val.
1912  Vector<long> Ptr(p+1); Vector<int> Ind(Nnonzero);
1913  Vector<T2, VectFull, Allocator2> Val(Nnonzero);
1914 
1915  for (int i2 = 0; i2 <= i; i2++)
1916  Ptr(i2) = B.GetPtr()[i2];
1917 
1918  for (j = 0; j < B.GetPtr()[i]; j++)
1919  {
1920  Ind(j) = B.GetInd()[j];
1921  Val(j) = B.GetData()[j];
1922  }
1923 
1924  // Now deals with the remaining lines.
1925  Nnonzero = A.GetPtr()[i];
1926  for (; i < p; i++)
1927  {
1928  kb = B.GetPtr()[i];
1929  if (kb < B.GetPtr()[i + 1])
1930  jb = B.GetInd()[kb];
1931  for (ka = A.GetPtr()[i]; ka < A.GetPtr()[i + 1]; ka++)
1932  {
1933  ja = A.GetInd()[ka];
1934  while (kb < B.GetPtr()[i + 1] && jb < ja)
1935  // For all elements in B that are before the ka-th element of A.
1936  {
1937  Ind(Nnonzero) = jb;
1938  Val(Nnonzero) = B.GetData()[kb];
1939  kb++;
1940  if (kb < B.GetPtr()[i + 1])
1941  jb = B.GetInd()[kb];
1942  Nnonzero++;
1943  }
1944 
1945  if (kb < B.GetPtr()[i + 1] && ja == jb)
1946  // The element in A is also in B.
1947  {
1948  Ind(Nnonzero) = jb;
1949  Val(Nnonzero) = B.GetData()[kb] + alpha * A.GetData()[ka];
1950  kb++;
1951  if (kb < B.GetPtr()[i + 1])
1952  jb = B.GetInd()[kb];
1953  }
1954  else
1955  {
1956  Ind(Nnonzero) = ja;
1957  Val(Nnonzero) = alpha * A.GetData()[ka];
1958  }
1959  Nnonzero++;
1960  }
1961 
1962  // The remaining elements from B.
1963  while (kb < B.GetPtr()[i + 1])
1964  {
1965  Ind(Nnonzero) = jb;
1966  Val(Nnonzero) = B.GetData()[kb];
1967  kb++;
1968  if (kb < B.GetPtr()[i + 1])
1969  jb = B.GetInd()[kb];
1970  Nnonzero++;
1971  }
1972 
1973  Ptr(i + 1) = Nnonzero;
1974  }
1975 
1976  B.SetData(B.GetM(), B.GetN(), Val, Ptr, Ind);
1977  }
1978 
1979 
1981 
1988  template<class T0, class T1, class Prop1, class Allocator1,
1989  class T2, class Prop2, class Allocator2>
1990  void AddMatrix(const T0& alpha,
1993  {
1994  Add_csr(alpha, A, B, B.GetM());
1995  }
1996 
1997 
1999 
2006  template<class T0, class T1, class Prop1, class Allocator1,
2007  class T2, class Prop2, class Allocator2>
2008  void AddMatrix(const T0& alpha,
2011  {
2012  Add_csr(alpha, A, B, B.GetN());
2013  }
2014 
2015 
2017 
2024  template<class T0, class T1, class Prop1, class Allocator1,
2025  class T2, class Prop2, class Allocator2>
2026  void AddMatrix(const T0& alpha,
2029  {
2030  Add_csr(alpha, A, B, B.GetM());
2031  }
2032 
2033 
2035 
2042  template<class T0, class T1, class Prop1, class Allocator1,
2043  class T2, class Prop2, class Allocator2>
2044  void AddMatrix(const T0& alpha,
2047  {
2048  Add_csr(alpha, A, B, B.GetN());
2049  }
2050 
2051 
2052  // ADD //
2054 
2055 
2057  // GETLU //
2058 
2059 
2061 
2072  template <class T0, class Prop0, class Storage0, class Allocator0>
2074  {
2075  int i, p, q, k;
2076  T0 temp, zero;
2077  SetComplexZero(zero);
2078 
2079  int ma = A.GetM();
2080 
2081 #ifdef SELDON_CHECK_BOUNDS
2082  int na = A.GetN();
2083  if (na != ma)
2084  throw WrongDim("GetLU(A)", "The matrix must be squared.");
2085 #endif
2086 
2087  if (Storage0::Sparse)
2088  throw WrongArgument("GetLU", "This function is intended to dense"
2089  " matrices only and not to sparse matrices");
2090 
2091  for (i = 0; i < ma; i++)
2092  {
2093  for (p = i; p < ma; p++)
2094  {
2095  temp = zero;
2096  for (k = 0; k < i; k++)
2097  temp += A(p, k) * A(k, i);
2098  A(p, i) -= temp;
2099  }
2100  for (q = i+1; q < ma; q++)
2101  {
2102  temp = zero;
2103  for (k = 0; k < i; k++)
2104  temp += A(i, k) * A(k, q);
2105  A(i, q) = (A(i,q ) - temp) / A(i, i);
2106  }
2107  }
2108  }
2109 
2110 
2111  // GETLU //
2113 
2114 
2116  // CHECKDIM //
2117 
2118 
2120 
2129  template <class T0, class Prop0, class Storage0, class Allocator0,
2130  class T1, class Prop1, class Storage1, class Allocator1,
2131  class T2, class Prop2, class Storage2, class Allocator2>
2135  string function)
2136  {
2137 #ifndef SELDON_WITHOUT_TO_STR_CHECKDIM
2138  string Achar = to_str(&A), Bchar = to_str(&B), Cchar = to_str(&C);
2139 #else
2140  string Achar("A"), Bchar("B"), Cchar("C");
2141 #endif
2142 
2143  if (B.GetM() != A.GetN() || C.GetM() != A.GetM() || B.GetN() != C.GetN())
2144  throw WrongDim(function, string("Operation A B + C -> C not permitted:")
2145  + string("\n A (") + Achar + string(") is a ")
2146  + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
2147  + string(" matrix;\n B (") + Bchar
2148  + string(") is a ") + to_str(B.GetM()) + string(" x ")
2149  + to_str(B.GetN()) + string(" matrix;\n C (")
2150  + Cchar + string(") is a ") + to_str(C.GetM())
2151  + string(" x ") + to_str(C.GetN()) + string(" matrix."));
2152  }
2153 
2154 
2156 
2166  template <class T0, class Prop0, class Storage0, class Allocator0,
2167  class T1, class Prop1, class Storage1, class Allocator1,
2168  class T2, class Prop2, class Storage2, class Allocator2>
2169  void CheckDim(const SeldonSide& side,
2173  string function)
2174  {
2175 #ifndef SELDON_WITHOUT_TO_STR_CHECKDIM
2176  string Achar = to_str(&A), Bchar = to_str(&B), Cchar = to_str(&C);
2177 #else
2178  string Achar("A"), Bchar("B"), Cchar("C");
2179 #endif
2180 
2181  if ( SeldonSide(side).Left() &&
2182  (B.GetM() != A.GetN() || C.GetM() != A.GetM()
2183  || B.GetN() != C.GetN()) )
2184  throw WrongDim(function, string("Operation A B + C -> C not permitted:")
2185  + string("\n A (") + Achar + string(") is a ")
2186  + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
2187  + string(" matrix;\n B (") + Bchar
2188  + string(") is a ") + to_str(B.GetM()) + string(" x ")
2189  + to_str(B.GetN()) + string(" matrix;\n C (")
2190  + Cchar + string(") is a ") + to_str(C.GetM())
2191  + string(" x ") + to_str(C.GetN()) + string(" matrix."));
2192  else if ( SeldonSide(side).Right() &&
2193  (B.GetN() != A.GetM() || C.GetM() != B.GetM()
2194  || A.GetN() != C.GetN()) )
2195  throw WrongDim(function, string("Operation B A + C -> C not permitted:")
2196  + string("\n A (") + Achar + string(") is a ")
2197  + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
2198  + string(" matrix;\n B (") + Bchar
2199  + string(") is a ") + to_str(B.GetM()) + string(" x ")
2200  + to_str(B.GetN()) + string(" matrix;\n C (")
2201  + Cchar + string(") is a ") + to_str(C.GetM())
2202  + string(" x ") + to_str(C.GetN()) + string(" matrix."));
2203  }
2204 
2205 
2207 
2217  template <class T0, class Prop0, class Storage0, class Allocator0,
2218  class T1, class Prop1, class Storage1, class Allocator1>
2219  void CheckDim(const SeldonTranspose& TransA,
2221  const SeldonTranspose& TransB,
2223  string function)
2224  {
2225 #ifndef SELDON_WITHOUT_TO_STR_CHECKDIM
2226  string Achar = to_str(&A), Bchar = to_str(&B);
2227 #else
2228  string Achar("A"), Bchar("B");
2229 #endif
2230 
2231  SeldonTranspose status_A(TransA);
2232  SeldonTranspose status_B(TransB);
2233  string op;
2234  if (status_A.Trans())
2235  op = string("A'");
2236  else if (status_A.ConjTrans())
2237  op = string("A*");
2238  else
2239  op = string("A");
2240  if (status_B.Trans())
2241  op += string(" B'");
2242  else if (status_B.ConjTrans())
2243  op += string(" B*");
2244  else
2245  op += string(" B");
2246  op = string("Operation ") + op + string(" not permitted:");
2247  if (B.GetM(status_B) != A.GetN(status_A))
2248  throw WrongDim(function, op
2249  + string("\n A (") + Achar + string(") is a ")
2250  + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
2251  + string(" matrix;\n B (") + Bchar
2252  + string(") is a ") + to_str(B.GetM()) + string(" x ")
2253  + to_str(B.GetN()) + string(" matrix."));
2254  }
2255 
2256 
2258 
2269  template <class T0, class Prop0, class Storage0, class Allocator0,
2270  class T1, class Prop1, class Storage1, class Allocator1,
2271  class T2, class Prop2, class Storage2, class Allocator2>
2272  void CheckDim(const SeldonTranspose& TransA,
2274  const SeldonTranspose& TransB,
2277  string function)
2278  {
2279 #ifndef SELDON_WITHOUT_TO_STR_CHECKDIM
2280  string Achar = to_str(&A), Bchar = to_str(&B), Cchar = to_str(&C);
2281 #else
2282  string Achar("A"), Bchar("B"), Cchar("C");
2283 #endif
2284 
2285  string op;
2286  if (TransA.Trans())
2287  op = string("A'");
2288  else if (TransA.ConjTrans())
2289  op = string("A*");
2290  else
2291  op = string("A");
2292  if (TransB.Trans())
2293  op += string(" B' + C");
2294  else if (TransB.ConjTrans())
2295  op += string(" B* + C");
2296  else
2297  op += string(" B + C");
2298  op = string("Operation ") + op + string(" not permitted:");
2299  if (B.GetM(TransB) != A.GetN(TransA) || C.GetM() != A.GetM(TransA)
2300  || B.GetN(TransB) != C.GetN())
2301  throw WrongDim(function, op
2302  + string("\n A (") + Achar + string(") is a ")
2303  + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
2304  + string(" matrix;\n B (") + Bchar
2305  + string(") is a ") + to_str(B.GetM()) + string(" x ")
2306  + to_str(B.GetN()) + string(" matrix;\n C (")
2307  + Cchar + string(") is a ") + to_str(C.GetM())
2308  + string(" x ") + to_str(C.GetN()) + string(" matrix."));
2309  }
2310 
2311 
2313 
2321  template <class T0, class Prop0, class Storage0, class Allocator0,
2322  class T1, class Prop1, class Storage1, class Allocator1>
2325  string function)
2326  {
2327  CheckDim(SeldonLeft, A, B, function);
2328  }
2329 
2330 
2332 
2341  template <class T0, class Prop0, class Storage0, class Allocator0,
2342  class T1, class Prop1, class Storage1, class Allocator1>
2343  void CheckDim(const SeldonSide& side,
2346  string function)
2347  {
2348 #ifndef SELDON_WITHOUT_TO_STR_CHECKDIM
2349  string Achar = to_str(&A), Bchar = to_str(&B);
2350 #else
2351  string Achar("A"), Bchar("B");
2352 #endif
2353 
2354  if (side.Left() && B.GetM() != A.GetN())
2355  throw WrongDim(function, string("Operation A B not permitted:")
2356  + string("\n A (") + Achar + string(") is a ")
2357  + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
2358  + string(" matrix;\n B (") + Bchar
2359  + string(") is a ") + to_str(B.GetM()) + string(" x ")
2360  + to_str(B.GetN()) + string(" matrix."));
2361  else if (side.Right() && B.GetN() != A.GetM())
2362  throw WrongDim(function, string("Operation B A not permitted:")
2363  + string("\n A (") + Achar + string(") is a ")
2364  + to_str(A.GetM()) + string(" x ") + to_str(A.GetN())
2365  + string(" matrix;\n B (") + Bchar
2366  + string(") is a ") + to_str(B.GetM()) + string(" x ")
2367  + to_str(B.GetN()) + string(" matrix."));
2368  }
2369 
2370 
2371  // CHECKDIM //
2373 
2374 
2376  // NORMS //
2377 
2378 
2380 
2384  template <class T, class Prop, class Storage, class Allocator>
2385  typename ClassComplexType<T>::Treal
2387  {
2388  if (Storage::Sparse)
2389  throw WrongArgument("MaxAbs", "This function is intended to dense"
2390  " matrices only and not to sparse matrices");
2391 
2392  typename ClassComplexType<T>::Treal res(0);
2393  for (int i = 0; i < A.GetM(); i++)
2394  for (int j = 0; j < A.GetN(); j++)
2395  res = max(res, ComplexAbs(A(i, j)) );
2396 
2397  return res;
2398  }
2399 
2400 
2402 
2406  template <class T, class Prop, class Storage, class Allocator>
2407  typename ClassComplexType<T>::Treal
2409  {
2410  if (Storage::Sparse)
2411  throw WrongArgument("Norm1", "This function is intended to dense"
2412  " matrices only and not to sparse matrices");
2413 
2414  typename ClassComplexType<T>::Treal res(0), sum;
2415  for (int j = 0; j < A.GetN(); j++)
2416  {
2417  sum = 0;
2418  for (int i = 0; i < A.GetM(); i++)
2419  sum += ComplexAbs( A(i, j) );
2420 
2421  res = max(res, sum);
2422  }
2423 
2424  return res;
2425  }
2426 
2427 
2429 
2433  template <class T, class Prop, class Storage, class Allocator>
2434  typename ClassComplexType<T>::Treal
2436  {
2437  if (Storage::Sparse)
2438  throw WrongArgument("NormInf", "This function is intended to dense"
2439  " matrices only and not to sparse matrices");
2440 
2441  typename ClassComplexType<T>::Treal res(0), sum;
2442  for (int i = 0; i < A.GetM(); i++)
2443  {
2444  sum = 0;
2445  for (int j = 0; j < A.GetN(); j++)
2446  sum += ComplexAbs( A(i, j) );
2447 
2448  res = max(res, sum);
2449  }
2450 
2451  return res;
2452  }
2453 
2454 
2456 
2460  template <class T, class Prop, class Allocator>
2461  typename ClassComplexType<T>::Treal
2463  {
2464  typename ClassComplexType<T>::Treal res(0);
2465  long taille = A.GetDataSize();
2466  for (long i = 0; i < taille; i++)
2467  res = max(res, ComplexAbs(A.GetData()[i]));
2468 
2469  return res;
2470  }
2471 
2472 
2474 
2478  template <class T, class Prop, class Allocator>
2479  typename ClassComplexType<T>::Treal
2481  {
2482  typedef typename ClassComplexType<T>::Treal Treal;
2483  Vector<Treal> sum(A.GetN());
2484  sum.Zero();
2485  for (int i = 0; i < A.GetM(); i++)
2486  for (long j = A.GetPtr()[i]; j < A.GetPtr()[i+1]; j++)
2487  sum(A.GetInd()[j]) += ComplexAbs( A.GetData()[j]);
2488 
2489  return sum.GetNormInf();
2490  }
2491 
2492 
2494 
2498  template <class T, class Prop, class Allocator>
2499  typename ClassComplexType<T>::Treal
2501  {
2502  typedef typename ClassComplexType<T>::Treal Treal;
2503  Treal res(0), sum;
2504  for (int i = 0; i < A.GetM(); i++)
2505  {
2506  sum = Treal(0);
2507  for (long j = A.GetPtr()[i]; j < A.GetPtr()[i+1]; j++)
2508  sum += ComplexAbs( A.GetData()[j]);
2509 
2510  res = max(res, sum);
2511  }
2512 
2513  return res;
2514  }
2515 
2516 
2518 
2522  template <class T, class Prop, class Allocator>
2523  typename ClassComplexType<T>::Treal
2525  {
2526  typename ClassComplexType<T>::Treal res(0);
2527  long taille = A.GetDataSize();
2528  for (long i = 0; i < taille; i++)
2529  res = max(res, ComplexAbs(A.GetData()[i]));
2530 
2531  return res;
2532  }
2533 
2534 
2536 
2540  template <class T, class Prop, class Allocator>
2541  typename ClassComplexType<T>::Treal
2543  {
2544  typedef typename ClassComplexType<T>::Treal Treal;
2545  Treal res(0), sum;
2546  for (int i = 0; i < A.GetN(); i++)
2547  {
2548  sum = Treal(0);
2549  for (long j = A.GetPtr()[i]; j < A.GetPtr()[i+1]; j++)
2550  sum += ComplexAbs( A.GetData()[j]);
2551 
2552  res = max(res, sum);
2553  }
2554 
2555  return res;
2556  }
2557 
2558 
2560 
2564  template <class T, class Prop, class Allocator>
2565  typename ClassComplexType<T>::Treal
2567  {
2568  typedef typename ClassComplexType<T>::Treal Treal;
2569  Vector<Treal> sum(A.GetM());
2570  sum.Zero();
2571  for (int i = 0; i < A.GetN(); i++)
2572  for (long j = A.GetPtr()[i]; j < A.GetPtr()[i+1]; j++)
2573  sum(A.GetInd()[j]) += ComplexAbs( A.GetData()[j]);
2574 
2575  return sum.GetNormInf();
2576  }
2577 
2578 
2580 
2584  template <class T, class Prop, class Allocator>
2585  typename ClassComplexType<T>::Treal
2587  {
2588  typename ClassComplexType<T>::Treal res(0);
2589  long taille = A.GetDataSize();
2590  for (long i = 0; i < taille; i++)
2591  res = max(res, ComplexAbs(A.GetData()[i]));
2592 
2593  return res;
2594  }
2595 
2596 
2598 
2602  template <class T, class Prop, class Allocator>
2603  typename ClassComplexType<T>::Treal
2605  {
2606  typedef typename ClassComplexType<T>::Treal Treal;
2607  Vector<Treal> sum(A.GetN());
2608  sum.Zero();
2609  for (int i = 0; i < A.GetM(); i++)
2610  for (long j = A.GetPtr()[i]; j < A.GetPtr()[i+1]; j++)
2611  {
2612  sum(A.GetInd()[j]) += ComplexAbs( A.GetData()[j]);
2613  if (A.GetInd()[j] != i)
2614  sum(i) += ComplexAbs(A.GetData()[j]);
2615  }
2616 
2617  return sum.GetNormInf();
2618  }
2619 
2620 
2622 
2626  template <class T, class Prop, class Allocator>
2627  typename ClassComplexType<T>::Treal
2629  {
2630  return Norm1(A);
2631  }
2632 
2633 
2635 
2639  template <class T, class Prop, class Allocator>
2640  typename ClassComplexType<T>::Treal
2642  {
2643  typename ClassComplexType<T>::Treal res(0);
2644  long taille = A.GetDataSize();
2645  for (long i = 0; i < taille; i++)
2646  res = max(res, ComplexAbs(A.GetData()[i]));
2647 
2648  return res;
2649  }
2650 
2651 
2653 
2657  template <class T, class Prop, class Allocator>
2658  typename ClassComplexType<T>::Treal
2660  {
2661  typedef typename ClassComplexType<T>::Treal Treal;
2662  Vector<Treal> sum(A.GetN());
2663  sum.Zero();
2664  for (int i = 0; i < A.GetM(); i++)
2665  for (long j = A.GetPtr()[i]; j < A.GetPtr()[i+1]; j++)
2666  {
2667  sum(A.GetInd()[j]) += ComplexAbs( A.GetData()[j]);
2668  if (A.GetInd()[j] != i)
2669  sum(i) += ComplexAbs(A.GetData()[j]);
2670  }
2671 
2672  return sum.GetNormInf();
2673  }
2674 
2675 
2677 
2681  template <class T, class Prop, class Allocator>
2682  typename ClassComplexType<T>::Treal
2684  {
2685  return Norm1(A);
2686  }
2687 
2688 
2689  // NORMS //
2691 
2692 
2694  // TRANSPOSE //
2695 
2696 
2698  template<class T, class Prop, class Storage, class Allocator>
2700  {
2701  if (Storage::Sparse)
2702  throw WrongArgument("Transpose", "This function is intended to dense"
2703  " matrices only and not to sparse matrices");
2704 
2705  int m = A.GetM();
2706  int n = A.GetN();
2707 
2708  if (m == n)
2709  {
2710  // for square matrices, we avoid allocation
2711  T tmp;
2712  for (int i = 0; i < m; i++)
2713  for (int j = 0; j < i; j++)
2714  {
2715  tmp = A(i, j);
2716  A(i, j) = A(j, i);
2717  A(j, i) = tmp;
2718  }
2719  }
2720  else
2721  {
2723  B = A;
2724  A.Reallocate(n, m);
2725  for (int i = 0; i < m; i++)
2726  for (int j = 0; j < n; j++)
2727  A.Get(j,i) = B(i,j);
2728 
2729  }
2730  }
2731 
2732 
2734  template<class T, class Prop, class Storage, class Allocator>
2737  {
2738  if (Storage::Sparse)
2739  throw WrongArgument("Transpose", "This function is intended to dense"
2740  " matrices only and not to sparse matrices");
2741 
2742  B.Reallocate(A.GetN(), A.GetM());
2743  for (int i = 0; i < A.GetM(); i++)
2744  for (int j = 0; j < A.GetN(); j++)
2745  B(j, i) = A(i, j);
2746  }
2747 
2748 
2750  template<class T, class Storage, class Allocator>
2752  {
2753  // A symmetric, then equal to its transpose
2754  }
2755 
2756 
2758  template<class T, class Storage, class Allocator>
2760  {
2761  // A hermitian, then transpose is conjugate
2762  Conjugate(A);
2763  }
2764 
2765 
2767  template<class T, class Storage, class Allocator>
2770  {
2771  // A symmetric, then equal to its transpose
2772  B = A;
2773  }
2774 
2775 
2777  template<class T, class Storage, class Allocator>
2780  {
2781  // A hermitian, B = conjugate(A)
2782  B = A;
2783  Conjugate(B);
2784  }
2785 
2786 
2788  template<class T, class Allocator>
2791  {
2792  B.Clear();
2793  int m = A.GetM();
2794  int n = A.GetN();
2795  long nnz = A.GetDataSize();
2796  Vector<long> ptr_T(n+1), ptr;
2797  Vector<int> ind_T(nnz), ind;
2798  Vector<T, VectFull, Allocator> data_T(nnz), data;
2799 
2800  ptr.SetData(m+1, A.GetPtr());
2801  ind.SetData(nnz, A.GetInd());
2802  data.SetData(nnz, A.GetData());
2803 
2804  ptr_T.Zero();
2805  ind_T.Zero();
2806  data_T.Zero();
2807 
2808  // For each column j, computes number of its non-zeroes and stores it in
2809  // ptr_T[j].
2810  for (long i = 0; i < nnz; i++)
2811  ptr_T(ind(i) + 1)++;
2812 
2813  // Computes the required number of non-zeroes ptr_T(j).
2814  for (int j = 1; j < n + 1; j++)
2815  ptr_T(j) += ptr_T(j - 1);
2816 
2817  Vector<int> row_ind(n+1);
2818  row_ind.Zero();
2819  for (int i = 0; i < m; i++)
2820  for (long jp = ptr(i); jp < ptr(i+1); jp++)
2821  {
2822  int j = ind(jp);
2823  long k = ptr_T(j) + row_ind(j);
2824  ++row_ind(j);
2825  data_T(k) = data(jp);
2826  ind_T(k) = i;
2827  }
2828 
2829  // sorting numbers
2830  for (int i = 0; i < n; i++)
2831  Sort(ptr_T(i), ptr_T(i+1)-1, ind_T, data_T);
2832 
2833  B.SetData(n, m, data_T, ptr_T, ind_T);
2834 
2835  data.Nullify();
2836  ptr.Nullify();
2837  ind.Nullify();
2838  }
2839 
2840 
2842  template<class T, class Allocator>
2844  {
2846  Transpose(Acopy, A);
2847  }
2848 
2849 
2851  template<class T, class Allocator>
2854  {
2855  B.Clear();
2856  int m = A.GetM();
2857  int n = A.GetN();
2858  long nnz = A.GetDataSize();
2859  Vector<long> ptr_T(m+1), ptr;
2860  Vector<int> ind_T(nnz), ind;
2861  Vector<T, VectFull, Allocator> data_T(nnz), data;
2862 
2863  ptr.SetData(n+1, A.GetPtr());
2864  ind.SetData(nnz, A.GetInd());
2865  data.SetData(nnz, A.GetData());
2866 
2867  ptr_T.Zero();
2868  ind_T.Zero();
2869  data_T.Zero();
2870 
2871  // For each column j, computes number of its non-zeroes and stores it in
2872  // ptr_T[j].
2873  for (long i = 0; i < nnz; i++)
2874  ptr_T(ind(i) + 1)++;
2875 
2876  // Computes the required number of non-zeroes ptr_T(j).
2877  for (int j = 1; j < m + 1; j++)
2878  ptr_T(j) += ptr_T(j - 1);
2879 
2880  Vector<int> row_ind(m+1);
2881  row_ind.Zero();
2882  for (int i = 0; i < n; i++)
2883  for (long jp = ptr(i); jp < ptr(i+1); jp++)
2884  {
2885  int j = ind(jp);
2886  long k = ptr_T(j) + row_ind(j);
2887  ++row_ind(j);
2888  data_T(k) = data(jp);
2889  ind_T(k) = i;
2890  }
2891 
2892  // sorting numbers
2893  for (int i = 0; i < m; i++)
2894  Sort(ptr_T(i), ptr_T(i+1)-1, ind_T, data_T);
2895 
2896  B.SetData(n, m, data_T, ptr_T, ind_T);
2897 
2898  data.Nullify();
2899  ptr.Nullify();
2900  ind.Nullify();
2901  }
2902 
2903 
2905  template<class T, class Allocator>
2907  {
2909  Transpose(Acopy, A);
2910  }
2911 
2912 
2914  template<class T, class Prop, class Storage, class Allocator>
2916  {
2917  long taille = A.GetDataSize();
2918  for (long i = 0; i < taille; i++)
2919  A.GetData()[i] = conjugate(A.GetData()[i]);
2920  }
2921 
2922 
2924  template<class T, class Prop, class Storage, class Allocator>
2927  {
2928  Transpose(A, B);
2929  Conjugate(B);
2930  }
2931 
2932 
2934  template<class T, class Prop, class Storage, class Allocator>
2936  {
2937  Transpose(A);
2938  Conjugate(A);
2939  }
2940 
2941 
2942  // TRANSPOSE //
2944 
2945 
2946 } // namespace Seldon.
2947 
2948 
2949 #endif
Seldon::TransposeConj
void TransposeConj(const Matrix< T, Prop, Storage, Allocator > &A, Matrix< T, Prop, Storage, Allocator > &B)
Matrix transposition and conjugation.
Definition: Functions_Matrix.cxx:2925
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::FloatDouble
Definition: Storage.hxx:365
Seldon::Matrix_SymSparse::GetInd
int * GetInd() const
Returns (row or column) indices of non-zero entries.
Definition: Matrix_SymSparseInline.cxx:153
Seldon::MltScalar
void MltScalar(const T0 &alpha, Array3D< T, Allocator > &A)
Multiplication of all elements of a 3D array by a scalar.
Definition: Array3D.cxx:539
Seldon::to_str
std::string to_str(const T &input)
Converts most types to string.
Definition: CommonInline.cxx:137
Seldon::Norm1
ClassComplexType< T >::Treal Norm1(const VectorExpression< T, E > &X)
returns 1-norm of an expression with vectors
Definition: Functions_BaseInline.cxx:140
Seldon::DenseSparseCollection
Definition: StorageInline.cxx:89
Seldon::Vector< int >
Seldon::Matrix_Sparse::GetDataSize
long GetDataSize() const
Returns the number of elements stored in memory.
Definition: Matrix_SparseInline.cxx:138
Seldon::class_SeldonNoTrans
Definition: MatrixFlag.hxx:62
Seldon::Vector< T, VectFull, Allocator >::Nullify
void Nullify()
Clears the vector without releasing memory.
Definition: VectorInline.cxx:476
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::Matrix< T, Prop, RowSparse, Allocator >
Row-major sparse-matrix class.
Definition: Matrix_Sparse.hxx:223
Seldon::Matrix< T, Prop, ColSparse, Allocator >
Column-major sparse-matrix class.
Definition: Matrix_Sparse.hxx:197
Seldon::Matrix_SymSparse::GetPtr
long * GetPtr() const
Returns (row or column) start indices.
Definition: Matrix_SymSparseInline.cxx:138
Seldon::Matrix_SymSparse::GetDataSize
long GetDataSize() const
Returns the number of elements stored in memory.
Definition: Matrix_SymSparseInline.cxx:126
Seldon::class_SeldonTrans
Definition: MatrixFlag.hxx:55
Seldon::Matrix_Base::GetData
pointer GetData() const
Returns a pointer to the data array.
Definition: Matrix_BaseInline.cxx:241
Seldon::Conjugate
void Conjugate(Matrix< T, Prop, Storage, Allocator > &A)
A is replaced by its conjugate.
Definition: Functions_Matrix.cxx:2915
Seldon::VirtualMatrix::GetN
int GetN() const
Returns the number of columns.
Definition: Matrix_BaseInline.cxx:80
Seldon::VirtualMatrix::GetM
int GetM() const
Returns the number of rows.
Definition: Matrix_BaseInline.cxx:69
Seldon::Matrix_Sparse::GetPtr
long * GetPtr() const
Returns (row or column) start indices.
Definition: Matrix_SparseInline.cxx:150
Seldon::Undefined
Definition: Errors.hxx:62
Seldon::MltMatrix
void MltMatrix(const Matrix< T0, Prop0, RowSparse, Allocator0 > &A, const Matrix< T1, Prop1, RowSparse, Allocator1 > &B, Matrix< T2, Prop2, RowSparse, Allocator2 > &C)
Multiplies two row-major sparse matrices in Harwell-Boeing format.
Definition: Functions_Matrix.cxx:207
Seldon::General
Definition: Properties.hxx:26
Seldon::Vector< T, VectFull, Allocator >
Full vector class.
Definition: Vector.hxx:88
Seldon::GetLU
void GetLU(Matrix< T0, Prop0, Storage0, Allocator0 > &A)
Returns the LU factorization of a matrix.
Definition: Functions_Matrix.cxx:2073
Seldon::CheckDim
void CheckDim(const Matrix< T0, Prop0, Storage0, Allocator0 > &A, const Matrix< T1, Prop1, Storage1, Allocator1 > &B, const Matrix< T2, Prop2, Storage2, Allocator2 > &C, string function)
Checks the compatibility of the dimensions.
Definition: Functions_Matrix.cxx:2132
Seldon::Matrix< T, Prop, RowSymSparse, Allocator >
Row-major sparse-matrix class.
Definition: Matrix_SymSparse.hxx:218
Seldon::NormInf
ClassComplexType< T >::Treal NormInf(const Matrix< T, Prop, Storage, Allocator > &A)
Returns the infinity-norm of a matrix.
Definition: Functions_Matrix.cxx:2435
Seldon::Matrix< T, Prop, ColSymSparse, Allocator >
Column-major sparse-matrix class.
Definition: Matrix_SymSparse.hxx:192
Seldon::Transpose
void Transpose(Matrix< T, Prop, Storage, Allocator > &A)
Matrix transposition.
Definition: Functions_Matrix.cxx:2699
Seldon::WrongArgument
Definition: Errors.hxx:76
Seldon::MaxAbs
ClassComplexType< T >::Treal MaxAbs(const Matrix< T, Prop, Storage, Allocator > &A)
Returns the maximum (in absolute value) of a matrix.
Definition: Functions_Matrix.cxx:2386
Seldon::SeldonSide
Definition: MatrixFlag.hxx:201
Seldon::WrongDim
Definition: Errors.hxx:102
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::MltAddMatrix
void MltAddMatrix(const T0 &alpha, const Matrix< T1, Prop1, Storage1, Allocator1 > &A, const Matrix< T2, Prop2, Storage2, Allocator2 > &B, const T3 &beta, Matrix< T4, Prop4, Storage4, Allocator4 > &C)
Multiplies two matrices, and adds the result to a third matrix.
Definition: Functions_Matrix.cxx:617
Seldon::NoMemory
Definition: Errors.hxx:90
Seldon::Matrix_Sparse::GetInd
int * GetInd() const
Returns (row or column) indices of non-zero entries.
Definition: Matrix_SparseInline.cxx:165
Seldon::AddMatrix
void AddMatrix(const T0 &alpha, const Matrix< T1, Prop1, Storage1, Allocator1 > &A, Matrix< T2, Prop2, Storage2, Allocator2 > &B)
Adds two matrices.
Definition: Functions_Matrix.cxx:1619
Seldon::ComplexAbs
T ComplexAbs(const T &val)
returns absolute value of val
Definition: CommonInline.cxx:309