SimpleMatrix::SimpleMatrix(const SiconosMatrix &m): SiconosMatrix(m.getNum()), _isPLUFactorized(), _isQRFactorized(false), _isPLUInversed(false) { // num is set in SiconosMatrix constructor with m.getNum() ... must be changed if m is Block unsigned int numM = m.getNum(); _isPLUFactorized= m.isPLUFactorized(); _isPLUInversed= m.isPLUInversed(); if (m.ipiv()) _ipiv.reset(new VInt(*(m.ipiv()))); if (numM == 0) // ie if m is Block, this matrix is set to a dense. { const BlockMatrix& mB = static_cast<const BlockMatrix&>(m); num = 1; // get number of blocks in a row/col of m. mat.Dense = new DenseMat(m.size(0), m.size(1)); ConstBlocksIterator1 it; ConstBlocksIterator2 it2; unsigned int posRow = 0; unsigned int posCol = 0; for (it = mB._mat->begin1(); it != mB._mat->end1(); ++it) { for (it2 = it.begin(); it2 != it.end(); ++it2) { setBlock(posRow, posCol, **it2); posCol += (*it2)->size(1); } posRow += (*it)->size(0); posCol = 0; } } else if (num == 1) { mat.Dense = new DenseMat(m.size(0), m.size(1)); noalias(*mat.Dense) = (*m.dense()); } else if (num == 2) mat.Triang = new TriangMat(*m.triang()); else if (num == 3) mat.Sym = new SymMat(*m.sym()); else if (num == 4) mat.Sparse = new SparseMat(*m.sparse()); else if (num == 5) mat.Banded = new BandedMat(*m.banded()); else if (num == 6) mat.Zero = new ZeroMat(m.size(0), m.size(1)); else // if(num == 7) mat.Identity = new IdentityMat(m.size(0), m.size(1)); }
// x block, y siconos void private_prod(const SiconosMatrix& A, unsigned int startRow, const SiconosVector& x, SiconosVector& y, bool init) { assert(!(A.isPLUFactorized()) && "A is PLUFactorized in prod !!"); // Computes y = subA *x (or += if init = false), subA being a sub-matrix of A, between el. of index (row) startRow and startRow + sizeY if (init) // y = subA * x , else y += subA * x y.zero(); private_addprod(A, startRow, 0, x, y); }
void subprod(const SiconosMatrix& A, const BlockVector& x, SiconosVector& y, const Index& coord, bool init) { assert(!(A.isPLUFactorized()) && "A is PLUFactorized in prod !!"); // Number of the subvector of x that handles element at position coord[4] std::size_t firstBlockNum = x.getNumVectorAtPos(coord[4]); // Number of the subvector of x that handles element at position coord[5] unsigned int lastBlockNum = x.getNumVectorAtPos(coord[5]); Index subCoord = coord; SPC::SiconosVector tmp = x[firstBlockNum]; std::size_t subSize = tmp->size(); // Size of the sub-vector const SP::Index xTab = x.tabIndex(); if (firstBlockNum != 0) { subCoord[4] -= (*xTab)[firstBlockNum - 1]; subCoord[5] = std::min(coord[5] - (*xTab)[firstBlockNum - 1], subSize); } else subCoord[5] = std::min(coord[5], subSize); if (firstBlockNum == lastBlockNum) { subprod(A, *tmp, y, subCoord, init); } else { unsigned int xPos = 0 ; // Position in x of the current sub-vector of x bool firstLoop = true; subCoord[3] = coord[2] + subCoord[5] - subCoord[4]; for (VectorOfVectors::const_iterator it = x.begin(); it != x.end(); ++it) { if ((*it)->getNum() == 0) SiconosMatrixException::selfThrow("subprod(A,x,y) error: not yet implemented for x block of blocks ..."); if (xPos >= firstBlockNum && xPos <= lastBlockNum) { tmp = x[xPos]; if (firstLoop) { subprod(A, *tmp, y, subCoord, init); firstLoop = false; } else { subCoord[2] += subCoord[5] - subCoord[4]; // !! old values for 4 and 5 subSize = tmp->size(); subCoord[4] = 0; subCoord[5] = std::min(coord[5] - (*xTab)[xPos - 1], subSize); subCoord[3] = subCoord[2] + subCoord[5] - subCoord[4]; subprod(A, *tmp, y, subCoord, false); } } xPos++; } } }
void prod(const SiconosVector& x, const SiconosMatrix& A, BlockVector& y, bool init) { assert(!(A.isPLUFactorized()) && "A is PLUFactorized in prod !!"); unsigned int startRow = 0; VectorOfVectors::const_iterator it; // For Each subvector of y, y[i], private_prod computes y[i] = subA x, subA being a submatrix of A corresponding to y[i] position. // private_prod takes into account the fact that x and y[i] may be block vectors. for (it = y.begin(); it != y.end(); ++it) { private_prod(createSPtrConstSiconosVector(x), createSPtrConstSiconosMatrix(A), startRow, *it, init); startRow += (*it)->size(); } }
void private_addprod(const SiconosMatrix& A, unsigned int startRow, unsigned int startCol, const BlockVector& x, SiconosVector& y) { assert(!(A.isPLUFactorized()) && "A is PLUFactorized in prod !!"); assert(!A.isBlock() && "private_addprod(A,start,x,y) error: not yet implemented for block matrix."); VectorOfVectors::const_iterator it; unsigned int startColBis = startCol; for (it = x.begin(); it != x.end(); ++it) { private_addprod(A, startRow, startColBis, **it, y); startColBis += (*it)->size(); } }
void prod(const SiconosMatrix& A, const BlockVector& x, SiconosVector& y, bool init) { assert(!(A.isPLUFactorized()) && "A is PLUFactorized in prod !!"); if (init) y.zero(); unsigned int startRow = 0; unsigned int startCol = 0; // In private_addprod, the sum of all blocks of x, x[i], is computed: y = Sum_i (subA x[i]), with subA a submatrix of A, // starting from position startRow in rows and startCol in columns. // private_prod takes also into account the fact that each block of x can also be a block. VectorOfVectors::const_iterator it; for (it = x.begin(); it != x.end(); ++it) { private_addprod(A, startRow, startCol, **it, y); startCol += (*it)->size(); } }
void private_addprod(const SiconosMatrix& A, unsigned startRow, unsigned int startCol, const SiconosVector& x, SiconosVector& y) { assert(!(A.isPLUFactorized()) && "A is PLUFactorized in prod !!"); assert(!A.isBlock() && "private_addprod(A,start,x,y) error: not yet implemented for block matrix."); // we take a submatrix subA of A, starting from row startRow to row (startRow+sizeY) and between columns startCol and (startCol+sizeX). // Then computation of y = subA*x + y. unsigned int numA = A.getNum(); unsigned int numY = y.getNum(); unsigned int numX = x.getNum(); unsigned int sizeX = x.size(); unsigned int sizeY = y.size(); assert(numX == numY && "private_addprod(A,start,x,y) error: not yet implemented for x and y of different types."); if (numY == 1 && numX == 1) { assert(y.dense() != x.dense()); if (numA == 1) noalias(*y.dense()) += prod(ublas::subrange(*A.dense(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x.dense()); else if (numA == 2) noalias(*y.dense()) += prod(ublas::subrange(*A.triang(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x.dense()); else if (numA == 3) noalias(*y.dense()) += prod(ublas::subrange(*A.sym(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x.dense()); else if (numA == 4) noalias(*y.dense()) += prod(ublas::subrange(*A.sparse(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x.dense()); else //if(numA==5) noalias(*y.dense()) += prod(ublas::subrange(*A.banded(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x.dense()); } else // x and y sparse { if (numA == 4) *y.sparse() += prod(ublas::subrange(*A.sparse(), startRow, startRow + sizeY, startCol, startCol + sizeX), *x.sparse()); else SiconosMatrixException::selfThrow("private_addprod(A,start,x,y) error: not yet implemented for x, y sparse and A not sparse."); } }