// 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_MATRIX_CONVERSIONS_CXX

namespace Seldon
{
 
 
/*
    From CSR formats to "Matlab" coordinate format.
  */

 
 
 
//! Conversion from RowSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop, RowSparse,
                               
Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int m = A.GetM();
   
int nnz = A.GetDataSize();
   
IndRow.Reallocate(nnz);
   
IndCol.Reallocate(nnz);
   
Val.Reallocate(nnz);
   
int* ptr = A.GetPtr();
   
int* ind = A.GetInd();
    T
* val = A.GetData();
   
for (i = 0; i < m; i++)
     
for (j = ptr[i]; j< ptr[i+1]; j++)
       
{
         
IndRow(j) = i + index;
         
IndCol(j) = ind[j] + index;
         
Val(j) = val[j];
       
}
 
}
 
 
 
//! Conversion from ColSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop, ColSparse,
                               
Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int n = A.GetN();
   
int nnz = A.GetDataSize();
   
IndCol.Reallocate(nnz);
   
IndRow.Reallocate(nnz);
   
Val.Reallocate(nnz);
   
int* ptr = A.GetPtr();
   
int* ind = A.GetInd();
    T
* val = A.GetData();
   
for (i = 0; i< n; i++)
     
for (j = ptr[i]; j< ptr[i+1]; j++)
       
{
         
IndCol(j) = i + index;
         
IndRow(j) = ind[j] + index;
         
Val(j) = val[j];
       
}
 
}
 
 
 
//! Conversion from RowSymSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop,
                               
RowSymSparse, Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int m = A.GetM();
   
int nnz = A.GetDataSize();
   
int* ptr = A.GetPtr();
   
int* ind = A.GetInd();
    T
* val = A.GetData();
   
if (sym)
     
{
        nnz
*= 2;
       
for (i = 0; i < m; i++)
         
if (ind[ptr[i]] == i)
            nnz
--;
       
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
IVect Ptr(m);
       
Ptr.Zero();
       
int nb = 0;
       
for (i = 0; i < m; i++)
         
for (j = ptr[i]; j < ptr[i + 1]; j++)
           
{
             
IndRow(nb) = i + index;
             
IndCol(nb) = ind[j] + index;
             
Val(nb) = val[j];
             
Ptr(ind[j])++;
              nb
++;
             
             
if (ind[j] != i)
               
{
                 
IndRow(nb) = ind[j] + index;
                 
IndCol(nb) = i + index;
                 
Val(nb) = val[j];
                 
Ptr(i)++;
                  nb
++;
               
}
           
}
       
       
// Sorting the row numbers...
       
Sort(IndRow, IndCol, Val);
       
       
// ... and the column numbers.
       
int offset = 0;
       
for (i = 0; i < m; i++)
         
{
           
Sort(offset, offset + Ptr(i) - 1, IndCol, Val);
            offset
+= Ptr(i);
         
}
       
     
}
   
else
     
{
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
for (i = 0; i < m; i++)
         
for (j = ptr[i]; j< ptr[i + 1]; j++)
           
{
             
IndRow(j) = i + index;
             
IndCol(j) = ind[j] + index;
             
Val(j) = val[j];
           
}
     
}
 
}
 
 
 
//! Conversion from ColSymSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop,
                               
ColSymSparse, Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int m = A.GetM();
   
int nnz = A.GetDataSize();
   
int* ptr = A.GetPtr();
   
int* ind = A.GetInd();
    T
* val = A.GetData();
   
if (sym)
     
{
        nnz
*= 2;
       
for (i = 0; i < m; i++)
         
for (j = ptr[i]; j < ptr[i + 1]; i++)
           
if (ind[j] == i)
              nnz
--;
       
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
IVect Ptr(m);
       
Ptr.Zero();
       
int nb = 0;
       
for (i = 0; i < m; i++)
         
for (j = ptr[i]; j < ptr[i + 1]; j++)
           
{
             
IndRow(nb) = i + index;
             
IndCol(nb) = ind[j] + index;
             
Val(nb) = val[j];
             
Ptr(ind[j])++;
              nb
++;
             
             
if (ind[j] != i)
               
{
                 
IndRow(nb) = ind[j] + index;
                 
IndCol(nb) = i + index;
                 
Val(nb) = val[j];
                 
Ptr(i)++;
                  nb
++;
               
}
           
}
       
       
// Sorting the row numbers...
       
Sort(IndRow, IndCol, Val);
       
       
// ...and the column numbers.
       
int offset = 0;
       
for (i = 0; i < m; i++)
         
{
           
Sort(offset, offset + Ptr(i) - 1, IndCol, Val);
            offset
+= Ptr(i);
         
}
       
     
}
   
else
     
{
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
for (i = 0; i < m; i++)
         
for (j = ptr[i]; j< ptr[i + 1]; j++)
           
{
             
IndRow(j) = i + index;
             
IndCol(j) = ind[j] + index;
             
Val(j) = val[j];
           
}
     
}
 
}
 
 
 
/*
    From Sparse Array formats to "Matlab" coordinate format.
  */

 
 
 
//! Conversion from ArrayRowSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop,
                               
ArrayRowSparse, Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int m = A.GetM();
   
int nnz = A.GetDataSize();
   
// Allocating arrays.
   
IndRow.Reallocate(nnz);
   
IndCol.Reallocate(nnz);
   
Val.Reallocate(nnz);
   
int nb = 0;
   
for (i = 0; i < m; i++)
     
for (j = 0; j < A.GetRowSize(i); j++)
       
{
         
IndRow(nb) = i + index;
         
IndCol(nb) = A.Index(i, j) + index;
         
Val(nb) = A.Value(i, j);
          nb
++;
       
}
 
}
 
 
 
//! Conversion from ArrayColSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop,
                               
ArrayColSparse, Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int n = A.GetN();
   
int nnz = A.GetDataSize();
   
// Allocating arrays.
   
IndRow.Reallocate(nnz);
   
IndCol.Reallocate(nnz);
   
Val.Reallocate(nnz);
   
int nb = 0;
   
for (i = 0; i < n; i++)
     
for (j = 0; j < A.GetColumnSize(i); j++)
       
{
         
IndRow(nb) = A.Index(i, j) + index;
         
IndCol(nb) = i + index;
         
Val(nb) = A.Value(i, j);
          nb
++;
       
}
 
}
 
 
 
//! Conversion from ArrayRowSymSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop,
                               
ArrayRowSymSparse, Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int m = A.GetM();
   
int nnz = A.GetDataSize();
   
if (sym)
     
{
        nnz
*= 2;
       
for (i = 0; i < m; i++)
         
for (j = 0; j < A.GetRowSize(i); j++)
           
if (A.Index(i, j) == i)
              nnz
--;
       
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
IVect Ptr(m);
       
Ptr.Zero();
       
int nb = 0;
       
for (i = 0; i < m; i++)
         
for (j = 0; j < A.GetRowSize(i); j++)
           
{
             
IndRow(nb) = i + index;
             
IndCol(nb) = A.Index(i, j) + index;
             
Val(nb) = A.Value(i, j);
             
Ptr(A.Index(i, j))++;
              nb
++;
             
             
if (A.Index(i, j) != i)
               
{
                 
IndRow(nb) = A.Index(i, j) + index;
                 
IndCol(nb) = i + index;
                 
Val(nb) = A.Value(i, j);
                 
Ptr(i)++;
                  nb
++;
               
}
           
}
       
       
// Sorting the row numbers...
       
Sort(IndRow, IndCol, Val);
       
       
// ...and the column numbers.
       
int offset = 0;
       
for (i = 0; i < m; i++)
         
{
           
Sort(offset, offset + Ptr(i) - 1, IndCol, Val);
            offset
+= Ptr(i);
         
}
     
}
   
else
     
{
       
// Allocating arrays.
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
int nb = 0;
       
for (i = 0; i < m; i++)
         
for (j = 0; j < A.GetRowSize(i); j++)
           
{
             
IndRow(nb) = i + index;
             
IndCol(nb) = A.Index(i, j) + index;
             
Val(nb) = A.Value(i, j);
              nb
++;
           
}
     
}
 
}
 
 
 
//! Conversion from ArrayColSymSparse to coordinate format.
 
template<class T, class Prop, class Allocator1, class Allocator2>
 
void
 
ConvertMatrix_to_Coordinates(const Matrix<T, Prop,
                               
ArrayColSymSparse, Allocator1>& A,
                               
IVect& IndRow, IVect& IndCol,
                               
Vector<T, VectFull, Allocator2>& Val,
                               
int index = 0, bool sym = false)
 
{
   
int i, j;
   
int m = A.GetM();
   
int nnz = A.GetDataSize();
   
if (sym)
     
{
        nnz
*= 2;
       
for (i = 0; i < m; i++)
         
for (j = 0; j < A.GetRowSize(i); j++)
           
if (A.Index(i, j) == i)
              nnz
--;
       
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
IVect Ptr(m);
       
Ptr.Zero();
       
int nb = 0;
       
for (i = 0; i < m; i++)
         
for (j = 0; j < A.GetRowSize(i); j++)
           
{
             
IndRow(nb) = i + index;
             
IndCol(nb) = A.Index(i, j) + index;
             
Val(nb) = A.Value(i, j);
             
Ptr(A.Index(i, j))++;
              nb
++;
             
             
if (A.Index(i, j) != i)
               
{
                 
IndRow(nb) = A.Index(i, j) + index;
                 
IndCol(nb) = i + index;
                 
Val(nb) = A.Value(i, j);
                 
Ptr(i)++;
                  nb
++;
               
}
           
}
       
       
// Sorting the row numbers...
       
Sort(IndRow, IndCol, Val);
       
       
// ...and the column numbers.
       
int offset = 0;
       
for (i = 0; i < m; i++)
         
{
           
Sort(offset, offset + Ptr(i) - 1, IndCol, Val);
            offset
+= Ptr(i);
         
}
     
}
   
else
     
{
       
// Allocating arrays.
       
IndRow.Reallocate(nnz);
       
IndCol.Reallocate(nnz);
       
Val.Reallocate(nnz);
       
int nb = 0;
       
for (i = 0; i < m; i++)
         
for (j = 0; j < A.GetColumnSize(i); j++)
           
{
             
IndRow(nb) = A.Index(i, j) + index;
             
IndCol(nb) = i + index;
             
Val(nb) = A.Value(i, j);
              nb
++;
           
}
     
}
 
}
 
 
 
/*
    From "Matlab" coordinate format to CSR formats.
  */

 
 
 
//! Conversion from coordinate format to RowSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop, RowSparse, Allocator>& A,
                                 
int index = 0)
 
{
   
// Assuming that there is no duplicate value.
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// Sorts the array 'IndRow'.
   
Sort(IndRow, IndCol, Val);

   
// Construction of array 'Ptr'.
   
IVect Ptr(m + 1);
   
Ptr.Zero();
   
for (int i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndRow(i) + 1)++;
     
}
   
   
for (i = 0; i < m; i++)
     
Ptr(i + 1) += Ptr(i);
   
   
// Sorts 'IndCol'.
   
for (i = 0; i < m; i++)
     
Sort(Ptr(i), Ptr(i + 1) - 1, IndCol, Val);
   
    A
.SetData(m, n, nnz, Val, Ptr, IndCol);
 
}
 
 
 
//! Conversion from coordinate format to ColSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop, ColSparse, Allocator>& A,
                                 
int index = 0)
 
{
   
// Assuming that there is no duplicate value.
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// Sorts the array 'IndCol'.
   
Sort(IndCol, IndRow, Val);

   
// Construction of array 'Ptr'.
   
IVect Ptr(n + 1);
   
Ptr.Zero();
   
for (i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndCol(i) + 1)++;
     
}
   
   
for (i = 0; i < n; i++)
     
Ptr(i + 1) += Ptr(i);
   
   
// Sorts 'IndRow'
   
for (i = 0; i < n; i++)
     
Sort(Ptr(i), Ptr(i + 1) - 1, IndRow, Val);
   
    A
.SetData(m, n, nnz, Val, Ptr, IndRow);
 
}
 
 
 
//! Conversion from coordinate format to RowSymSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop, RowSymSparse, Allocator>& A,
                                 
int index = 0)
 
{
   
// Assuming there is no duplicate value.
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// First, removing the lower part of the matrix (if present).
   
int nb_low = 0;
   
for (i = 0; i < nnz; i++)
     
if (IndRow(i) > IndCol(i))
        nb_low
++;
   
   
if (nb_low > 0)
     
{
       
int nb = 0;
       
for (i = 0; i < nnz; i++)
         
if (IndRow(i) <= IndCol(i))
           
{
             
IndRow(nb) = IndRow(i);
             
IndCol(nb) = IndCol(i);
             
Val(nb) = Val(i);
              nb
++;
           
}
       
       
IndRow.Resize(nb);
       
IndCol.Resize(nb);
       
Val.Resize(nb);
        nnz
= nb;
     
}

   
// Sorts the array 'IndRow'.
   
Sort(IndRow, IndCol, Val);

   
// Construction of array 'Ptr'.
   
IVect Ptr(m + 1);
   
Ptr.Zero();
   
for (int i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndRow(i) + 1)++;
     
}
   
   
for (int i = 0; i < m; i++)
     
Ptr(i + 1) += Ptr(i);
   
   
// Sorts 'IndCol'.
   
for (int i = 0; i < m; i++)
     
Sort(Ptr(i), Ptr(i + 1) - 1, IndCol, Val);
   
    A
.SetData(m, n, nnz, Val, Ptr, IndCol);
 
}
 
 
 
//! Conversion from coordinate format to ColSymSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop, ColSymSparse, Allocator>& A,
                                 
int index = 0)
 
{
   
// Assuming there is no duplicate value.
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// First, removing the lower part of the matrix (if present).
   
int nb_low = 0;
   
for (i = 0; i < nnz; i++)
     
if (IndRow(i) > IndCol(i))
        nb_low
++;
   
   
if (nb_low > 0)
     
{
       
int nb = 0;
       
for (i = 0; i < nnz; i++)
         
if (IndRow(i) <= IndCol(i))
           
{
             
IndRow(nb) = IndRow(i);
             
IndCol(nb) = IndCol(i);
             
Val(nb) = Val(i);
              nb
++;
           
}
       
       
IndRow.Resize(nb);
       
IndCol.Resize(nb);
       
Val.Resize(nb);
        nnz
= nb;
     
}

   
// Sorts the array 'IndRow'.
   
Sort(IndRow, IndCol, Val);

   
// Construction of array 'Ptr'.
   
IVect Ptr(m + 1);
   
Ptr.Zero();
   
for (i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndRow(i) + 1)++;
     
}
   
   
for (i = 0; i < m; i++)
     
Ptr(i + 1) += Ptr(i);
   
   
// Sorts 'IndCol'.
   
for (int i = 0; i < m; i++)
     
Sort(Ptr(i), Ptr(i + 1) - 1, IndCol, Val);
   
    A
.SetData(m, n, nnz, Val, Ptr, IndCol);
 
}
 
 
 
/*
    From Sparse Array formats to "Matlab" coordinate format.
  */

 
 
 
//! Conversion from coordinate format to ArrayRowSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop, ArrayRowSparse,
                                 
Allocator>& A,
                                 
int index = 0)
 
{
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i, j;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// Sorts the array 'IndRow'.
   
Sort(IndRow, IndCol, Val);

   
// Number of elements per row.
   
IVect Ptr(m);
   
Ptr.Zero();
   
for (i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndRow(i))++;
     
}
   
   
// Fills matrix 'A'.
    A
.Reallocate(m, n);
   
int offset = 0;
   
for (i = 0; i < m; i++)
     
if (Ptr(i) > 0)
       
{
          A
.ReallocateRow(i, Ptr(i));
         
for (j = 0; j < Ptr(i); j++)
           
{
              A
.Index(i, j) = IndCol(offset + j);
              A
.Value(i, j) = Val(offset + j);
           
}
          offset
+= Ptr(i);
       
}
   
   
// Assembles 'A' to sort column numbers.
    A
.Assemble();
 
}
 
 
 
//! Conversion from coordinate format to ArrayColSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop, ArrayColSparse,
                                 
Allocator>& A,
                                 
int index = 0)
 
{
   
// Assuming there is no duplicate value.
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i, j;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// Sorts array 'IndCol'.
   
Sort(IndCol, IndRow, Val);

   
// Construction of array 'Ptr'.
   
IVect Ptr(n);
   
Ptr.Zero();
   
for (i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndCol(i))++;
     
}
   
   
// Fills matrix 'A'.
    A
.Reallocate(m, n);
   
int offset = 0;
   
for (i = 0; i < n; i++)
     
if (Ptr(i) > 0)
       
{
          A
.ReallocateColumn(i, Ptr(i));
         
for (j = 0; j < Ptr(i); j++)
           
{
              A
.Index(i, j) = IndRow(offset + j);
              A
.Value(i, j) = Val(offset + j);
           
}
          offset
+= Ptr(i);
       
}
   
   
// Assembles 'A' to sort row numbers.
    A
.Assemble();
 
}
 
 
 
//! Conversion from coordinate format to ArrayRowSymSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop,
                                 
ArrayRowSymSparse, Allocator>& A,
                                 
int index = 0)
 
{
   
// Assuming that there is no duplicate value.
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i, j;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// First, removing the lower part of the matrix (if present).
   
int nb_low = 0;
   
for (i = 0; i < nnz; i++)
     
if (IndRow(i) > IndCol(i))
        nb_low
++;
   
   
if (nb_low > 0)
     
{
       
int nb = 0;
       
for (i = 0; i < nnz; i++)
         
if (IndRow(i) <= IndCol(i))
           
{
             
IndRow(nb) = IndRow(i);
             
IndCol(nb) = IndCol(i);
             
Val(nb) = Val(i);
              nb
++;
           
}
       
       
IndRow.Resize(nb);
       
IndCol.Resize(nb);
       
Val.Resize(nb);
        nnz
= nb;
     
}

   
// Sorts the array 'IndRow'.
   
Sort(IndRow, IndCol, Val);

   
// Construction of array 'Ptr'.
   
IVect Ptr(m);
   
Ptr.Zero();
   
for (i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndRow(i))++;
     
}
   
   
// Fills matrix 'A'.
    A
.Reallocate(m, n);
   
int offset = 0;
   
for (i = 0; i < m; i++)
     
if (Ptr(i) > 0)
       
{
          A
.ReallocateRow(i, Ptr(i));
         
for (j = 0; j < Ptr(i); j++)
           
{
              A
.Index(i, j) = IndCol(offset + j);
              A
.Value(i, j) = Val(offset + j);
           
}
          offset
+= Ptr(i);
       
}
   
   
// Assembles 'A' to sort column numbers.
    A
.Assemble();
 
}
 
 
 
//! Conversion from coordinate format to ArrayColSymSparse.
 
template<class T, class Prop, class Allocator>
 
void
 
ConvertMatrix_from_Coordinates(IVect& IndRow, IVect& IndCol,
                                 
Vector<T, VectFull, Allocator>& Val,
                                 
Matrix<T, Prop,
                                 
ArrayColSymSparse, Allocator>& A,
                                 
int index = 0)
 
{
   
// Assuming that there is no duplicate value.
   
if (IndRow.GetM() <= 0)
     
return;
   
   
int i, j;

   
int row_max = IndRow.GetNormInf();
   
int col_max = IndCol.GetNormInf();
   
int m = row_max - index + 1;
   
int n = col_max - index + 1;
   
int nnz = IndRow.GetM();
   
   
// First, removing the lower part of the matrix (if present).
   
int nb_low = 0;
   
for (i = 0; i < nnz; i++)
     
if (IndRow(i) > IndCol(i))
        nb_low
++;
   
   
if (nb_low > 0)
     
{
       
int nb = 0;
       
for (i = 0; i < nnz; i++)
         
if (IndRow(i) <= IndCol(i))
           
{
             
IndRow(nb) = IndRow(i);
             
IndCol(nb) = IndCol(i);
             
Val(nb) = Val(i);
              nb
++;
           
}
       
       
IndRow.Resize(nb);
       
IndCol.Resize(nb);
       
Val.Resize(nb);
        nnz
= nb;
     
}

   
// Sorts the array 'IndRow'.
   
Sort(IndRow, IndCol, Val);

   
// Construction of array 'Ptr'.
   
IVect Ptr(m);
   
Ptr.Zero();
   
for (i = 0; i < nnz; i++)
     
{
       
IndRow(i) -= index;
       
IndCol(i) -= index;
       
Ptr(IndRow(i))++;
     
}
   
   
// Fills matrix 'A'.
    A
.Reallocate(m, n);
   
int offset = 0;
   
for (i = 0; i < m; i++)
     
if (Ptr(i) > 0)
       
{
          A
.ReallocateColumn(i, Ptr(i));
         
for (j = 0; j < Ptr(i); j++)
           
{
              A
.Index(i, j) = IndCol(offset + j);
              A
.Value(i, j) = Val(offset + j);
           
}
          offset
+= Ptr(i);
       
}
   
   
// Assembles 'A' to sort column numbers.
    A
.Assemble();
 
}
 
 
 
/*
    From CSR to other CSR formats.
  */

 
 
 
//! B = A.
 
template<class T, class Prop, class Alloc1, class Alloc2>
 
void Copy(const Matrix<T, Prop, ColSparse, Alloc1>& A,
           
Matrix<T, Prop, ColSparse, Alloc2>& B)
 
{
   
int i;

   
int m = A.GetM(), n = A.GetN(), nnz = A.GetDataSize();
   
int* ptr_ = A.GetPtr();
   
int* ind_ = A.GetInd();
    T
* data_ = A.GetData();
   
   
IVect Ptr(n+1), Ind(nnz);
   
Vector<T, VectFull, Alloc2> Val(nnz);
   
for (i = 0; i <= n; i++)
     
Ptr(i) = ptr_[i];
   
   
for (i = 0; i < nnz; i++)
     
{
       
Ind(i) = ind_[i];
       
Val(i) = data_[i];
     
}
   
    B
.SetData(m, n, Val, Ptr, Ind);
 
}
 
 
 
//! Conversion from row-sparse to column-sparse.
 
template<class T, class Prop, class Alloc1, class Alloc2>
 
void Copy(const Matrix<T, Prop, RowSparse, Alloc1>& A,
           
Matrix<T, Prop, ColSparse, Alloc2>& B)
 
{
   
int i, j;

   
int m = A.GetM(), n = A.GetN(), nnz = A.GetDataSize();
   
int* ptr_ = A.GetPtr();
   
int* ind_ = A.GetInd();
    T
* data_ = A.GetData();
   
   
// Computation of the indices of the beginning of columns.
   
IVect Ptr(n + 1);
   
Ptr.Fill(0);
   
// Counting the number of entries per column.
   
for (i = 0; i < nnz; i++)
     
Ptr(ind_[i])++;
   
   
// Incrementing in order to get indices.
   
int increment = 0, size, num_col;
   
for (i = 0; i < n; i++)
     
{
        size
= Ptr(i);
       
Ptr(i) = increment;
        increment
+= size;
     
}
   
// Last index.
   
Ptr(n) = increment;
   
   
// 'Offset' will be used to get current positions of new entries.
   
IVect Offset = Ptr;
   
IVect Ind(nnz);
   
Vector<T, VectFull, Alloc2> Val(nnz);
   
   
// Loop over rows.
   
for (i = 0; i < m; i++)
     
for (j = ptr_[i]; j < ptr_[i + 1]; j++)
       
{
          num_col
= ind_[j];
         
Ind(Offset(num_col)) = i;
         
Val(Offset(num_col)) = data_[j];
         
Offset(num_col)++;
       
}
   
    B
.SetData(m, n, Val, Ptr, Ind);
 
}
 
 
 
//! Conversion from row-sparse to column-sparse.
 
template<class T, class Prop1, class Prop2,
           
class Storage, class Alloc1, class Alloc2>
 
void
 
ConvertMatrixSymSparse_to_ColSparse(const Matrix<T, Prop1,
                                     
Storage, Alloc1>& A,
                                     
Matrix<T, Prop2, ColSparse, Alloc2>& B)
 
{
   
int i, j;

   
int m = A.GetM(), n = A.GetN();
   
int* ptr_ = A.GetPtr();
   
int* ind_ = A.GetInd();
    T
* data_ = A.GetData();
   
   
// Computation of the indices of the beginning of columns.
   
IVect Ptr(n + 1);
   
Ptr.Fill(0);
   
// Counting the number of entries per column.
   
for (i = 0; i < m; i++)
     
for (j = ptr_[i]; j < ptr_[i + 1]; j++)
       
{
         
Ptr(ind_[j])++;
         
if (i != ind_[j])
           
Ptr(i)++;
       
}
   
   
// Incrementing in order to get indices.
   
int nnz = 0, size, num_col;
   
for (i = 0; i < n; i++)
     
{
        size
= Ptr(i);
       
Ptr(i) = nnz;
        nnz
+= size;
     
}
   
// Last index.
   
Ptr(n) = nnz;
   
   
// 'Offset' will be used to get current positions of new entries.
   
IVect Offset = Ptr;
   
IVect Ind(nnz);
   
Vector<T, VectFull, Alloc2> Val(nnz);
   
   
// Loop over rows.
   
for (i = 0; i < m; i++)
     
for (j = ptr_[i]; j < ptr_[i + 1]; j++)
       
{
          num_col
= ind_[j];
         
Ind(Offset(num_col)) = i;
         
Val(Offset(num_col)) = data_[j];
         
Offset(num_col)++;
         
if (i != ind_[j])
           
{
             
Ind(Offset(i)) = num_col;
             
Val(Offset(i)) = data_[j];
             
Offset(i)++;
           
}
       
}
   
    B
.SetData(m, n, Val, Ptr, Ind);
 
}
 
 
 
//! Conversion from RowSymSparse to column-sparse.
 
template<class T, class Prop1, class Prop2, class Alloc1, class Alloc2>
 
void Copy(const Matrix<T, Prop1, RowSymSparse, Alloc1>& A,
           
Matrix<T, Prop2, ColSparse, Alloc2>& B)
 
{
   
ConvertMatrixSymSparse_to_ColSparse(A, B);
 
}
 
 
 
//! Conversion from ColSymSparse to column-sparse.
 
template<class T, class Prop1, class Prop2, class Alloc1, class Alloc2>
 
void Copy(const Matrix<T, Prop1, ColSymSparse, Alloc1>& A,
           
Matrix<T, Prop2, ColSparse, Alloc2>& B)
 
{
   
ConvertMatrixSymSparse_to_ColSparse(A, B);
 
}
 
 
 
/*
    From ArraySparse matrices to CSR matrices.
  */

 
 
 
//! Conversion from ArrayRowSparse to RowSparse.
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void Copy(const Matrix<T0, Prop0, ArrayRowSparse,Allocator0>& mat_array,
           
Matrix<T1, Prop1, RowSparse, Allocator1>& mat_csr)
 
{
   
int i, k;

   
// Matrix (m,n) with 'nnz' entries.
   
int nnz = mat_array.GetDataSize();
   
int m = mat_array.GetM();
   
int n = mat_array.GetN();
   
   
// Allocating arrays needed for CSR format.
   
Vector<T1> Val(nnz);
   
IVect IndRow(m + 1);
   
IVect IndCol(nnz);
   
   
// Filling the arrays.
   
int ind = 0;
   
IndRow(0) = 0;
   
for (i = 0; i < m; i++)
     
{
       
for (k = 0; k < mat_array.GetRowSize(i); k++)
         
{
           
IndCol(ind) = mat_array.Index(i, k);
           
Val(ind) = mat_array.Value(i, k);
            ind
++;
         
}
       
IndRow(i + 1) = ind;
     
}
   
    mat_csr
.SetData(m, n, Val, IndRow, IndCol);
 
}
 
 
 
//! Conversion from ArrayRowSparse to ColSparse.
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void Copy(const Matrix<T0, Prop0, ArrayRowSparse,Allocator0>& mat_array,
           
Matrix<T1, Prop1, ColSparse, Allocator1>& mat_csr)
 
{
   
int i;

   
// Matrix (m,n) with nnz entries.
   
int nnz = mat_array.GetDataSize();
   
int m = mat_array.GetM();
   
int n = mat_array.GetN();
   
   
// Conversion in coordinate format.
   
Vector<T1> Val;
   
IVect IndRow, IndCol;
   
ConvertMatrix_to_Coordinates(mat_array, IndRow, IndCol, Val);
   
   
// Sorting with respect to column numbers.
   
Sort(IndCol, IndRow, Val);
   
   
// Constructing pointer array 'Ptr'.
   
IVect Ptr(n + 1);
   
   
// Counting non-zero entries per column.
   
for (i = 0; i < nnz; i++)
     
Ptr(IndCol(i) + 1)++;
   
   
// Accumulation to get pointer array.
   
Ptr(0) = 0;
   
for (i = 0; i < n; i++)
     
Ptr(i + 1) += Ptr(i);
   
    mat_csr
.SetData(m, n, Val, Ptr, IndRow);
 
}
 
 
 
//! Conversion from ArrayRowSymSparse to RowSymSparse.
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void Copy(const Matrix<T0, Prop0, ArrayRowSymSparse,Allocator0>& mat_array,
           
Matrix<T1, Prop1, RowSymSparse, Allocator1>& mat_csr)
 
{
   
int i, k;

   
// Number of rows and non-zero entries.
   
int nnz = mat_array.GetDataSize();
   
int m = mat_array.GetM();
   
   
// Allocation of arrays for CSR format.
   
Vector<T1> Val(nnz);
   
Vector<int, VectFull, CallocAlloc<int> > IndRow(m + 1);
   
Vector<int, VectFull, CallocAlloc<int> > IndCol(nnz);
   
   
int ind = 0;
   
IndRow(0) = 0;
   
for (i = 0; i < m; i++)
     
{
       
for (k = 0; k < mat_array.GetRowSize(i); k++)
         
{
           
IndCol(ind) = mat_array.Index(i, k);
           
Val(ind) = mat_array.Value(i, k);
            ind
++;
         
}
       
IndRow(i + 1) = ind;
     
}
   
    mat_csr
.SetData(m, m, Val, IndRow, IndCol);
 
}
 
 
 
//! Conversion from ArrayRowComplexSparse to RowComplexSparse.
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void
 
Copy(const Matrix<T0, Prop0, ArrayRowComplexSparse, Allocator0>& mat_array,
       
Matrix<T1, Prop1, RowComplexSparse, Allocator1>& mat_csr)
 
{
   
int i, k;

   
// Non-zero entries (real and imaginary part).
   
int nnz_real = mat_array.GetRealDataSize();
   
int nnz_imag = mat_array.GetImagDataSize();
   
int m = mat_array.GetM();
   
   
// Allocation of arrays for CSR.
   
Vector<T0> Val_real(nnz_real), Val_imag(nnz_imag);
   
IVect IndRow_real(m + 1), IndRow_imag(m + 1);
   
IVect IndCol_real(nnz_real), IndCol_imag(nnz_imag);
   
   
int ind_real = 0, ind_imag = 0;
   
IndRow_real(0) = 0;
   
IndRow_imag(0) = 0;
   
// Loop over rows.
   
for (i = 0; i < m; i++)
     
{
       
for (k = 0; k < mat_array.GetRealRowSize(i); k++)
         
{
           
IndCol_real(ind_real) = mat_array.IndexReal(i, k);
           
Val_real(ind_real) = mat_array.ValueReal(i, k);
            ind_real
++;
         
}
       
       
IndRow_real(i + 1) = ind_real;
       
for (k = 0; k < mat_array.GetImagRowSize(i); k++)
         
{
           
IndCol_imag(ind_imag) = mat_array.IndexImag(i, k);
           
Val_imag(ind_imag) = mat_array.ValueImag(i, k);
            ind_imag
++;
         
}
       
       
IndRow_imag(i + 1) = ind_imag;
     
}
   
    mat_csr
.SetData(m, m, Val_real, IndRow_real, IndCol_real,
                   
Val_imag, IndRow_imag, IndCol_imag);
 
}
 
 
 
//! Conversion from ArrayRowSymComplexSparse to RowSymComplexSparse.
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void
 
Copy(const Matrix<T0, Prop0,
       
ArrayRowSymComplexSparse, Allocator0>& mat_array,
       
Matrix<T1, Prop1, RowSymComplexSparse, Allocator1>& mat_csr)
 
{
   
int i, k;

   
// Non-zero entries (real and imaginary part).
   
int nnz_real = mat_array.GetRealDataSize();
   
int nnz_imag = mat_array.GetImagDataSize();
   
int m = mat_array.GetM();
   
   
// Allocation of arrays for CSR.
   
Vector<T0> Val_real(nnz_real), Val_imag(nnz_imag);
   
IVect IndRow_real(m + 1), IndRow_imag(m + 1);
   
IVect IndCol_real(nnz_real), IndCol_imag(nnz_imag);
   
   
int ind_real = 0, ind_imag = 0;
   
IndRow_real(0) = 0;
   
IndRow_imag(0) = 0;
   
// Loop over rows.
   
for (i = 0; i < m; i++)
     
{
       
for (k = 0; k < mat_array.GetRealRowSize(i); k++)
         
{
           
IndCol_real(ind_real) = mat_array.IndexReal(i, k);
           
Val_real(ind_real) = mat_array.ValueReal(i, k);
            ind_real
++;
         
}
       
       
IndRow_real(i + 1) = ind_real;
       
for (int k = 0; k < mat_array.GetImagRowSize(i); k++)
         
{
           
IndCol_imag(ind_imag) = mat_array.IndexImag(i, k);
           
Val_imag(ind_imag) = mat_array.ValueImag(i, k);
            ind_imag
++;
         
}
       
       
IndRow_imag(i + 1) = ind_imag;
     
}
   
    mat_csr
.SetData(m, m, Val_real, IndRow_real, IndCol_real,
                   
Val_imag, IndRow_imag, IndCol_imag);
 
}
 
 
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void Copy(const Matrix<T0, Prop0, ArrayRowSymSparse, Allocator0>& A,
           
Matrix<T1, Prop1, ArrayRowSparse, Allocator1>& B)
 
{
   
int i, j;

   
int nnz = A.GetDataSize();
   
int n = A.GetM();
   
IVect IndRow(nnz),IndCol(nnz);
   
Vector<T1> Val(nnz);
   
int ind = 0;
   
for (i = 0; i < n; i++)
     
for (j = 0; j < A.GetRowSize(i); j++)
       
if (A.Index(i, j) != i)
         
{
           
IndRow(ind) = i;
           
IndCol(ind) = A.Index(i, j);
           
Val(ind) = A.Value(i, j);
            ind
++;
         
}
   
Sort(ind, IndCol, IndRow, Val);
    nnz
= ind;
    ind
= 0;
   
    B
.Reallocate(n, n);
   
for (i = 0; i < n; i++)
     
{
       
int first_index = ind;
       
while (ind < nnz && IndCol(ind) <= i)
          ind
++;
       
int size_lower = ind - first_index;
       
int size_upper = A.GetRowSize(i);
       
int size_row = size_lower + size_upper;
        B
.ResizeRow(i, size_row);
        ind
= first_index;
       
for (j = 0; j < size_lower; j++)
         
{
            B
.Index(i, j) = IndRow(ind);
            B
.Value(i, j) = Val(ind);
            ind
++;
         
}
       
for (j = 0; j < size_upper; j++)
         
{
            B
.Index(i, size_lower + j) = A.Index(i, j);
            B
.Value(i, size_lower + j) = A.Value(i, j);
         
}
        B
.AssembleRow(i);
     
}
 
}
 
 
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void Copy(const Matrix<T0, Prop0, ArrayRowSymSparse, Allocator0>& A,
           
Matrix<T1, Prop1, ArrayColSparse, Allocator1>& B)
 
{
   
int i, j;

   
int nnz = A.GetDataSize();
   
int n = A.GetM();
   
IVect IndRow(nnz), IndCol(nnz);
   
Vector<T1> Val(nnz);
   
int ind = 0;
   
for (i = 0; i < n; i++)
     
for (j = 0; j < A.GetRowSize(i); j++)
       
if (A.Index(i, j) != i)
         
{
           
IndRow(ind) = i;
           
IndCol(ind) = A.Index(i, j);
           
Val(ind) = A.Value(i, j);
            ind
++;
         
}
   
Sort(ind, IndCol, IndRow, Val);
    nnz
= ind;
    ind
= 0;
   
    B
.Reallocate(n, n);
   
for (i = 0; i < n; i++)
     
{
       
int first_index = ind;
       
while (ind < nnz && IndCol(ind) <= i)
          ind
++;
       
int size_lower = ind - first_index;
       
int size_upper = A.GetRowSize(i);
       
int size_row = size_lower + size_upper;
        B
.ResizeColumn(i, size_row);
        ind
= first_index;
       
for (j = 0; j < size_lower; j++)
         
{
            B
.Index(i, j) = IndRow(ind);
            B
.Value(i, j) = Val(ind);
            ind
++;
         
}
       
for (j = 0; j < size_upper; j++)
         
{
            B
.Index(i, size_lower + j) = A.Index(i, j);
            B
.Value(i, size_lower + j) = A.Value(i, j);
         
}
        B
.AssembleColumn(i);
     
}
 
}
 
 
 
//! Conversion from ArrayColSparse to ColSparse.
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void Copy(const Matrix<T0, Prop0, ArrayColSparse, Allocator0>& mat_array,
           
Matrix<T1, Prop1, ColSparse, Allocator1>& mat_csc)
 
{
   
int i, k;

   
// Matrix (m,n) with 'nnz' entries.
   
int nnz = mat_array.GetDataSize();
   
int m = mat_array.GetM();
   
int n = mat_array.GetN();
   
   
// Allocating arrays needed for CSC format.
   
Vector<T1> Val(nnz);
   
IVect IndRow(nnz);
   
IVect IndCol(n+1);
   
   
// Filling the arrays.
   
int ind = 0;
   
IndCol(0) = 0;
   
for (i = 0; i < n; i++)
     
{
       
for (k = 0; k < mat_array.GetColumnSize(i); k++)
         
{
           
IndRow(ind) = mat_array.Index(i, k);
           
Val(ind) = mat_array.Value(i, k);
            ind
++;
         
}
       
IndCol(i + 1) = ind;
     
}
   
    mat_csc
.SetData(m, n, Val, IndCol, IndRow);
 
}
 
 
 
//! Conversion from ArrayRowSparse to ArrayColSparse.
 
template<class T0, class Prop0, class Allocator0,
           
class T1, class Prop1, class Allocator1>
 
void Copy(const Matrix<T0, Prop0, ArrayRowSparse,Allocator0>& A,
           
Matrix<T1, Prop1, ArrayColSparse, Allocator1>& B)
 
{
   
int i;
   
   
// Matrix (m,n) with nnz entries.
   
int nnz = A.GetDataSize();
   
int n = A.GetN();
   
   
// Conversion in coordinate format.
   
Vector<T1> Val;
   
IVect IndRow, IndCol;
   
ConvertMatrix_to_Coordinates(A, IndRow, IndCol, Val);
   
   
// Sorting with respect to column numbers.
   
Sort(IndCol, IndRow, Val);
   
   
// Constructing pointer array 'Ptr'.
   
IVect Ptr(n + 1);
   
   
// Counting non-zero entries per column.
   
for (i = 0; i < nnz; i++)
     
Ptr(IndCol(i) + 1)++;
   
   
// Accumulation to get pointer array.
   
Ptr(0) = 0;
   
for (i = 0; i < n; i++)
     
Ptr(i + 1) += Ptr(i);
   
   
// we fill matrix B
   
for (int i = 0; i < n; i++)
     
{
       
int size_col = Ptr(i+1) - Ptr(i);
       
if (size_col > 0)
         
{
            B
.ReallocateColumn(i, size_col);
           
for (int j = Ptr(i); j < Ptr(i+1); j++)
             
{
                B
.Index(i, j-Ptr(i)) = IndRow(j);
                B
.Value(i, j-Ptr(i)) = Val(j);
             
}
         
}
     
}
 
}
 
} // namespace Seldon.

#define SELDON_FILE_FUNCTIONS_MATRIX_CXX
#endif