// Copyright (C) 2003-2009 Marc Duruflé
// Copyright (C) 2001-2009 Vivien Mallet
//
// This file is part of the linear-algebra library Seldon,
// http://seldon.sourceforge.net/.
//
// Seldon is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your option)
// any later version.
//
// Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Seldon. If not, see http://www.gnu.org/licenses/.


#ifndef SELDON_FILE_FUNCTIONS_MATRIX_ARRAY_CXX

/*
  Functions defined in this file:
  (storage ArrayRowSparse, ArrayColSparse, etc)
 
  alpha.M*X + beta.Y -> Y
  MltAdd(alpha, M, X, beta, Y)
 
  alpha.A + B -> B
  Add(alpha, A, B)
 
  alpha.M -> M
  Mlt(alpha, M)
 
*/


namespace Seldon
{
 

 
////////////
 
// MltAdd //
 
 
 
/*** ArrayRowSymComplexSparse ***/
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha, const Matrix<T1, Symmetric,
             
ArrayRowSymComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (beta == T4(0))
      C
.Fill(T3(0));
   
else
     
Mlt(beta, C);
   
   
int m = A.GetM(), n, p;
    T1 val
;
    T3 val_cplx
;
   
if (alpha == T0(1))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val
= A.ValueReal(i, k);
               
if (p == i)
                  C
(i) += val * B(i);
               
else
                 
{
                    C
(i) += val * B(p);
                    C
(p) += val * B(i);
                 
}
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val
= A.ValueImag(i, k);
               
if (p == i)
                  C
(i) += complex<T1>(0, val) * B(i);
               
else
                 
{
                    C
(i) += complex<T1>(0, val) * B(p);
                    C
(p) += complex<T1>(0, val) * B(i);
                 
}
             
}
         
}
     
}
   
else // alpha != 1.
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val_cplx
= alpha * A.ValueReal(i, k);
               
if (p == i)
                  C
(i) += val_cplx * B(i);
               
else
                 
{
                    C
(i) += val_cplx * B(p);
                    C
(p) += val_cplx * B(i);
                 
}
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val_cplx
= alpha * complex<T1>(0, A.ValueImag(i, k));
               
if (p == i)
                  C
(i) += val_cplx * B(i);
               
else
                 
{
                    C
(i) += val_cplx * B(p);
                    C
(p) += val_cplx * B(i);
                 
}
             
}
         
}
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonNoTrans& Trans, const Matrix<T1, Symmetric,
             
ArrayRowSymComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
MltAdd(alpha, A, B, beta, C);
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonTrans& Trans, const Matrix<T1, Symmetric,
             
ArrayRowSymComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
MltAdd(alpha, A, B, beta, C);
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonConjTrans& Trans, const Matrix<T1, Symmetric,
             
ArrayRowSymComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (beta == T4(0))
      C
.Fill(T3(0));
   
else
     
Mlt(beta, C);
   
int m = A.GetM(),n,p;
    T1 val
;
    T3 val_cplx
;
   
if (alpha == T0(1))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val
= A.ValueReal(i, k);
               
if (p == i)
                  C
(i) += val * B(i);
               
else
                 
{
                    C
(i) += val * B(p);
                    C
(p) += val * B(i);
                 
}
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val
= A.ValueImag(i, k);
               
if (p == i)
                  C
(i) -= complex<T1>(0, val) * B(i);
               
else
                 
{
                    C
(i) -= complex<T1>(0, val) * B(p);
                    C
(p) -= complex<T1>(0, val) * B(i);
                 
}
             
}
         
}
     
}
   
else
     
{
       
// alpha different from 1
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val_cplx
= alpha * A.ValueReal(i, k);
               
if (p == i)
                  C
(i) += val_cplx * B(i);
               
else
                 
{
                    C
(i) += val_cplx * B(p);
                    C
(p) += val_cplx * B(i);
                 
}
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val_cplx
= alpha * complex<T1>(0, A.ValueImag(i, k));
               
if (p == i)
                  C
(i) -= val_cplx * B(i);
               
else
                 
{
                    C
(i) -= val_cplx * B(p);
                    C
(p) -= val_cplx * B(i);
                 
}
             
}
         
}
     
}
 
}
 
   
 
/*** ArrayRowComplexSparse ***/
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha, const Matrix<T1, General,
             
ArrayRowComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (beta == T4(0))
      C
.Fill(T3(0));
   
else
     
Mlt(beta, C);
   
int m = A.GetM(), n, p;
    T1 val
;
    T3 val_cplx
;
   
if (alpha == T0(1, 0))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val
= A.ValueReal(i, k);
                C
(i) += val * B(p);
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val
= A.ValueImag(i, k);
                C
(i) += complex<T1>(0, val) * B(p);
             
}
         
}
     
}
   
else
     
{
       
// alpha different from 1
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val_cplx
= alpha * A.ValueReal(i, k);
                C
(i) += val_cplx * B(p);
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val_cplx
= alpha * complex<T1>(0, A.ValueImag(i, k));
                C
(i) += val_cplx * B(p);
             
}
         
}
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonNoTrans& Trans, const Matrix<T1, General,
             
ArrayRowComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
MltAdd(alpha, A, B, beta, C);
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonTrans& Trans, const Matrix<T1, General,
             
ArrayRowComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (beta == T4(0))
      C
.Fill(T3(0));
   
else
     
Mlt(beta, C);
   
int m = A.GetM(),n,p;
    T1 val
;
    T3 val_cplx
;
   
if (alpha == T0(1))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val
= A.ValueReal(i, k);
                C
(p) += val * B(i);
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val
= A.ValueImag(i, k);
                C
(p) += complex<T1>(0, val) * B(i);
             
}
         
}
     
}
   
else
     
{
       
// alpha different from 1
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val_cplx
= alpha * A.ValueReal(i, k);
                C
(p) += val_cplx * B(i);
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val_cplx
= alpha * complex<T1>(0, A.ValueImag(i, k));
                C
(p) += val_cplx * B(i);
             
}
         
}
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonConjTrans& Trans, const Matrix<T1, General,
             
ArrayRowComplexSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (beta == T4(0))
      C
.Fill(T3(0));
   
else
     
Mlt(beta, C);
   
int m = A.GetM(),n,p;
    T1 val
;
    T3 val_cplx
;
   
if (alpha == T0(1))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val
= A.ValueReal(i, k);
                C
(p) += val * B(i);
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val
= A.ValueImag(i, k);
                C
(p) -= complex<T1>(0, val) * B(i);
             
}
         
}
     
}
   
else
     
{
       
// alpha different from 1
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRealRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexReal(i, k);
                val_cplx
= alpha * A.ValueReal(i, k);
                C
(p) += val_cplx * B(i);
             
}
            n
= A.GetImagRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.IndexImag(i, k);
                val_cplx
-= alpha * complex<T1>(0, A.ValueImag(i, k));
                C
(p) += val_cplx * B(i);
             
}
         
}
     
}
 
}
 
 
 
/*** ArrayRowSymSparse ***/
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha, const Matrix<T1, Symmetric,
             
ArrayRowSymSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (B.GetM() <= 0)
     
return;
   
    T3 zero
(B(0));
    zero
*= 0;
   
   
if (beta == zero)
      C
.Fill(zero);
   
else
     
Mlt(beta, C);
   
   
int m = A.GetM(), n, p;
    T1 val
;
   
if (alpha == T0(1))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.Index(i, k);
                val
= A.Value(i, k);
               
               
if (p == i)
                  C
(i) += val * B(i);
               
else
                 
{
                    C
(i) += val * B(p);
                    C
(p) += val * B(i);
                 
}
             
}
         
}
     
}
   
else
     
{
       
// alpha different from 1
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.Index(i, k);
                val
= alpha * A.Value(i, k);
               
               
if (p==i)
                  C
(i) += val * B(i);
               
else
                 
{
                    C
(i) += val * B(p);
                    C
(p) += val * B(i);
                 
}
             
}
         
}
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonNoTrans& Trans, const Matrix<T1, Symmetric,
             
ArrayRowSymSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
MltAdd(alpha, A, B, beta, C);
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonTrans& Trans, const Matrix<T1, Symmetric,
             
ArrayRowSymSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
MltAdd(alpha, A, B, beta, C);
 
}
 
 
 
/*** ArrayRowSparse ***/
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (beta == T4(0))
      C
.Fill(T3(0));
   
else
     
Mlt(beta, C);
   
int m = A.GetM(), n, p;
    T1 val
;
   
if (alpha == T0(1))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.Index(i, k);
                val
= A.Value(i, k);
                C
(i) += val * B(p);
             
}
         
}
     
}
   
else // alpha != 1.
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.Index(i, k);
                val
= A.Value(i, k);
                C
(i) += alpha * val * B(p);
             
}
         
}
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonNoTrans& Trans,
             
const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T4, VectFull, Allocator3>& C)
 
{
   
MltAdd(alpha, A, B, beta, C);
 
}
 
 
 
template<class T0, class T1, class T2, class T3, class T4,
           
class Allocator1, class Allocator2, class Allocator3>
 
void MltAdd(const T0& alpha,
             
const class_SeldonTrans& Trans,
             
const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
             
const Vector<T2, VectFull, Allocator2>& B,
             
const T4& beta,
             
Vector<T3, VectFull, Allocator3>& C)
 
{
   
if (beta == T4(0))
      C
.Fill(T3(0));
   
else
     
Mlt(beta, C);
   
int m = A.GetM(), n, p;
    T1 val
;
   
if (alpha == T0(1))
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.Index(i, k);
                val
= A.Value(i, k);
                C
(p) += val * B(i);
             
}
         
}
     
}
   
else // alpha != 1.
     
{
       
for (int i = 0 ; i < m ; i++)
         
{
            n
= A.GetRowSize(i);
           
for (int k = 0; k < n ; k++)
             
{
                p
= A.Index(i, k);
                val
= A.Value(i, k);
                C
(p) += alpha * val * B(i);
             
}
         
}
     
}
 
}
 
 
 
// MltAdd //
 
////////////
 
 
 
 
/////////
 
// Add //
 
 
 
template<class T0, class T1, class T2, class Allocator1, class Allocator2>
 
void Add(const T0& alpha,
           
const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
           
Matrix<T2, General, ArrayRowSparse, Allocator2>& B)
 
{
   
int m = B.GetM(),n;
   
Vector<T2, VectFull, Allocator2> value;
   
for (int i = 0 ; i < m ; i++)
     
{
        n
= A.GetRowSize(i);
        value
.Reallocate(n);
       
for (int j = 0; j < n; j++)
          value
(j) = T2(A.Value(i, j));
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n, A.GetIndex(i), value.GetData());
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class Allocator1, class Allocator2>
 
void Add(const T0& alpha,
           
const Matrix<T1, Symmetric, ArrayRowSymSparse, Allocator1>& A,
           
Matrix<T2, Symmetric, ArrayRowSymSparse, Allocator2>& B)
 
{
   
int m = B.GetM(),n;
   
Vector<T2, VectFull, Allocator2> value;
   
for (int i = 0 ; i < m ; i++)
     
{
        n
= A.GetRowSize(i);
        value
.Reallocate(n);
       
for (int j = 0; j < n; j++)
          value
(j) = A.Value(i, j);
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n, A.GetIndex(i), value.GetData());
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class Allocator1, class Allocator2>
 
void Add(const T0& alpha,
           
const Matrix<T1, Symmetric,
           
ArrayRowSymComplexSparse, Allocator1>& A,
           
Matrix<T2, Symmetric, ArrayRowSymComplexSparse, Allocator2>& B)
 
{
   
int m = B.GetM(), n, ni;
   
Vector<complex<T2> > value;
   
IVect index;
   
for (int i = 0 ; i < m ; i++)
     
{
        n
= A.GetRealRowSize(i);
        ni
= A.GetImagRowSize(i);
        value
.Reallocate(n + ni);
        index
.Reallocate(n + ni);
       
for (int j = 0; j < n; j++)
         
{
            value
(j) = A.ValueReal(i, j);
            index
(j) = A.IndexReal(i, j);
         
}
       
       
for (int j = 0; j < ni; j++)
         
{
            value
(j+n) = complex<T2>(0, 1) * A.ValueImag(i, j);
            index
(j+n) = A.IndexImag(i, j);
         
}
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n+ni, index, value);
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class Allocator1, class Allocator2>
 
void Add(const T0& alpha, const Matrix<T1, Symmetric,
           
ArrayRowSymComplexSparse, Allocator1>& A,
           
Matrix<T2, Symmetric, ArrayRowSymSparse, Allocator2>& B)
 
{
   
int m = B.GetM(), n;
   
Vector<T2, VectFull, Allocator2> value;
   
for (int i = 0 ; i < m ; i++)
     
{
        n
= A.GetRealRowSize(i);
        value
.Reallocate(n);
       
for (int j = 0; j < n; j++)
          value
(j) = A.ValueReal(i, j);
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n, A.GetRealInd(i), value.GetData());
        n
= A.GetImagRowSize(i);
        value
.Reallocate(n);
       
for (int j = 0; j < n; j++)
          value
(j) = complex<T1>(0, 1) * A.ValueImag(i, j);
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n, A.GetImagInd(i), value.GetData());
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class Allocator1, class Allocator2>
 
void Add(const T0& alpha, const Matrix<T1, General,
           
ArrayRowComplexSparse, Allocator1>& A,
           
Matrix<T2, Symmetric, ArrayRowSparse, Allocator2>& B)
 
{
   
int m = B.GetM(),n;
   
Vector<T2, VectFull, Allocator2> value;
   
for (int i = 0; i < m; i++)
     
{
        n
= A.GetRealRowSize(i);
        value
.Reallocate(n);
       
for (int j = 0; j < n; j++)
          value
(j) = A.ValueReal(i, j);
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n, A.GetRealInd(i), value.GetData());
        n
= A.GetImagRowSize(i);
        value
.Reallocate(n);
       
for (int j = 0; j < n; j++)
          value
(j) = complex<T1>(0, 1) * A.ValueImag(i, j);
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n, A.GetImagInd(i), value.GetData());
     
}
 
}
 
 
 
template<class T0, class T1, class T2, class Allocator1,class Allocator2>
 
void Add(const T0& alpha, const Matrix<T1, General,
           
ArrayRowComplexSparse, Allocator1>& A,
           
Matrix<T2, General, ArrayRowComplexSparse, Allocator2>& B)
 
{
   
int m = B.GetM(), n, ni;
   
Vector<complex<T2> > value; IVect index;
   
for (int i = 0 ; i < m ; i++)
     
{
        n
= A.GetRealRowSize(i);
        ni
= A.GetImagRowSize(i);
        value
.Reallocate(n + ni);
        index
.Reallocate(n + ni);
       
for (int j = 0; j < n; j++)
         
{
            value
(j) = A.ValueReal(i, j);
            index
(j) = A.IndexReal(i, j);
         
}
       
       
for (int j = 0; j < n; j++)
         
{
            value
(n+j) = complex<T2>(0, 1) * A.ValueImag(i, j);
            index
(n+j) = A.IndexImag(i, j);
         
}
       
       
Mlt(alpha, value);
        B
.AddInteractionRow(i, n+ni, index, value);
     
}
 
}
 
 
 
// C = C + complex(A,B)
 
template<class T0, class T1, class T2, class T3, class Allocator1,
           
class Allocator2, class Allocator3>
 
void Add(const T0& alpha,
           
const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
           
const Matrix<T2, General, ArrayRowSparse, Allocator2>& B,
           
Matrix<complex<T3>, General, ArrayRowSparse, Allocator3>& C)
 
{
   
int m = B.GetM(),n1,n2,size_row;;
   
Vector<complex<T3>, VectFull, Allocator3> val_row;
   
IVect ind_row;
   
for (int i = 0 ; i < m ; i++)
     
{
        n1
= A.GetRowSize(i);
        n2
= B.GetRowSize(i);
        size_row
= n1 + n2;
        val_row
.Reallocate(size_row);
        ind_row
.Reallocate(size_row);
       
for (int j = 0 ; j < n1 ; j++)
         
{
            ind_row
(j) = A.Index(i, j);
            val_row
(j) = alpha*complex<T3>(A.Value(i, j), 0);
         
}
       
       
for (int j = 0 ; j < n2 ; j++)
         
{
            ind_row
(j+n1) = B.Index(i, j);
            val_row
(j+n1) = alpha * complex<T3>(B.Value(i, j));
         
}
        C
.AddInteractionRow(i, size_row, ind_row, val_row);
     
}
 
}
 

 
// C = C + complex(A,B)
 
template<class T0, class T1, class T2, class T3,
           
class Allocator1, class Allocator2, class Allocator3>
 
void Add(const T0& alpha,
           
const Matrix<T1, Symmetric, ArrayRowSymSparse, Allocator1>& A,
           
const Matrix<T2, Symmetric, ArrayRowSymSparse, Allocator2>& B,
           
Matrix<complex<T3>, Symmetric, ArrayRowSymSparse, Allocator3>& C)
 
{
   
int m = B.GetM(), n1, n2, size_row;
   
Vector<complex<T3>, VectFull, Allocator3> val_row;
   
IVect ind_row;
   
for (int i = 0 ; i < m ; i++)
     
{
        n1
= A.GetRowSize(i);
        n2
= B.GetRowSize(i);
        size_row
= n1 + n2;
        val_row
.Reallocate(size_row);
        ind_row
.Reallocate(size_row);
       
for (int j = 0 ; j < n1 ; j++)
         
{
            ind_row
(j) = A.Index(i, j);
            val_row
(j) = alpha * complex<T3>(A.Value(i, j), 0);
         
}
       
       
for (int j = 0 ; j < n2 ; j++)
         
{
            ind_row
(j+n1) = B.Index(i, j);
            val_row
(j+n1) = alpha * complex<T3>(B.Value(i, j));
         
}
       
        C
.AddInteractionRow(i, size_row, ind_row, val_row);
     
}
 
}
 
 
 
// C = C + complex(A,B)
 
template<class T0, class T1, class T2, class T3,
           
class Allocator1, class Allocator2, class Allocator3>
 
void Add(const T0& alpha,
           
const Matrix<T1, Symmetric, ArrayRowSymSparse, Allocator1>& A,
           
const Matrix<T2, Symmetric, ArrayRowSymSparse, Allocator2>& B,
           
Matrix<T3, Symmetric, ArrayRowSymComplexSparse, Allocator3>& C)
 
{
   
int m = B.GetM(), n, ni;
   
Vector<complex<T3> > value; IVect index;
   
for (int i = 0 ; i < m ; i++)
     
{
        n
= A.GetRowSize(i);
        ni
= B.GetRowSize(i);
        value
.Reallocate(n+ni);
        index
.Reallocate(n+ni);
       
for (int j = 0; j < n; j++)
         
{
            value
(j) = A.Value(i, j);
            index
(j) = A.Index(i, j);
         
}
       
       
for (int j = 0; j < ni; j++)
         
{
            value
(n+j) = complex<T3>(0, 1) * B.Value(i, j);
            index
(n+j) = B.Index(i, j);
         
}
       
       
Mlt(alpha, value);
        C
.AddInteractionRow(i, n+ni, index, value);
     
}
 
}
 
 
 
// C = C + complex(A,B)
 
template<class T0, class T1, class T2, class T3,
           
class Allocator1, class Allocator2, class Allocator3>
 
void Add(const T0& alpha,
           
const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
           
const Matrix<T2, General, ArrayRowSparse, Allocator2>& B,
           
Matrix<T3, General, ArrayRowComplexSparse, Allocator3>& C)
 
{
   
int m = B.GetM(), n, ni;
   
Vector<complex<T3> > value;
   
IVect index;
   
for (int i = 0 ; i < m ; i++)
     
{
        n
= A.GetRowSize(i);
        ni
= B.GetRowSize(i);
        value
.Reallocate(n + ni);
        index
.Reallocate(n + ni);
       
for (int j = 0; j < n; j++)
         
{
            value
(j) = A.Value(i, j);
            index
(j) = A.Index(i, j);
         
}
       
       
for (int j = 0; j < ni; j++)
         
{
            value
(n+j) = complex<T3>(0, 1) * B.Value(i, j);
            index
(n+j) = B.Index(i, j);
         
}
       
       
Mlt(alpha, value);
        C
.AddInteractionRow(i, n+ni, index, value);
     
}
 
}
 
 
 
// Add //
 
/////////
 
 
 
 
/////////
 
// Mlt //
 
 
 
template<class T0, class T, class Allocator>
 
void Mlt(const T0& alpha, Matrix<T, General, ArrayRowSparse, Allocator>& A)
 
{
   
for (int i = 0; i < A.GetM(); i++)
     
for (int j = 0; j < A.GetRowSize(i); j++)
        A
.Value(i,j) *= alpha;
 
}
 
 
 
template<class T0, class T, class Allocator>
 
void Mlt(const T0& alpha, Matrix<T, General, ArrayColSparse, Allocator>& A)
 
{
   
for (int i = 0; i < A.GetN(); i++)
     
for (int j = 0; j < A.GetColSize(i); j++)
        A
.Value(i,j) *= alpha;
 
}
 
 
 
template<class T0, class T, class Allocator>
 
void Mlt(const T0& alpha,
           
Matrix<T, Symmetric, ArrayRowSymSparse, Allocator>& A)
 
{
   
for (int i = 0; i < A.GetM(); i++)
     
for (int j = 0; j < A.GetRowSize(i); j++)
        A
.Value(i,j) *= alpha;
 
}
 
 
 
template<class T0, class T, class Allocator>
 
void Mlt(const T0& alpha,
           
Matrix<T, Symmetric, ArrayColSymSparse, Allocator>& A)
 
{
   
for (int i = 0; i < A.GetN(); i++)
     
for (int j = 0; j < A.GetColSize(i); j++)
        A
.Value(i,j) *= alpha;
 
}
 
 
 
template<class T0, class T, class Allocator>
 
void Mlt(const T0& alpha,
           
Matrix<T, General, ArrayRowComplexSparse, Allocator>& A)
 
{
   
for (int i = 0; i < A.GetM(); i++)
     
{
       
for (int j = 0; j < A.GetRealRowSize(i); j++)
          A
.ValueReal(i,j) *= alpha;
       
for (int j = 0; j < A.GetImagRowSize(i); j++)
          A
.ValueImag(i,j) *= alpha;
     
}
 
}
 
 
 
template<class T0, class T, class Allocator>
 
void Mlt(const T0& alpha, Matrix<T, Symmetric,
           
ArrayRowSymComplexSparse, Allocator>& A)
 
{
   
for (int i = 0; i < A.GetM(); i++)
     
{
       
for (int j = 0; j < A.GetRealRowSize(i); j++)
          A
.ValueReal(i,j) *= alpha;
       
       
for (int j = 0; j < A.GetImagRowSize(i); j++)
          A
.ValueImag(i,j) *= alpha;
     
}
 
}
 
 
 
// Matrix-matrix product (sparse matrix against full matrix)
 
template<class T1, class Allocator1, class T2, class Prop2,
           
class Storage2, class Allocator2, class T3, class Prop3,
           
class Storage3, class Allocator3>
 
void Mlt(const Matrix<T1, General, ArrayRowSparse, Allocator1>& A,
           
const Matrix<T2, Prop2, Storage2, Allocator2>& B,
           
Matrix<T3, Prop3, Storage3, Allocator3>& C)
 
{
   
int m = A.GetM();
   
int n = B.GetN();
    C
.Reallocate(m,n);
    T3 val
;
   
for (int i = 0; i < m; i++)
     
for (int j = 0; j < n; j++)
       
{
          val
= T3(0);
         
for (int ind = 0; ind < A.GetRowSize(i); ind++)
           
{
             
int k = A.Index(i, ind);
              val
+= A.Value(i, ind) * B(k, j);
           
}
          C
(i, j) = val;
       
}
 
}
 
 
 
// Mlt //
 
/////////
 
 
} // namespace Seldon

#define SELDON_FILE_FUNCTIONS_MATRIX_ARRAY_CXX
#endif