2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Bernard HUGUENEY
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
18 #include <Eigen/Sparse>
25 #include <Eigen/IterativeLinearSolvers>
26 #include <Eigen/SparseCholesky>
30 #include "tostring_common.hxx"
32 #include "matrixiterator.hxx"
33 #include "types_subtraction.hxx"
34 #include "types_addition.hxx"
35 #include "types_multiplication.hxx"
36 #include "configvariable.hxx"
37 #include "scilabWrite.hxx"
39 #include "types_tools.hxx"
41 #include "sparseOp.hxx"
45 #include "elem_common.h"
50 typedef Eigen::Triplet<double> RealTriplet_t;
51 typedef Eigen::Triplet<std::complex<double>> CplxTriplet_t;
52 typedef Eigen::Triplet<bool> BoolTriplet_t;
54 /* used for debuging output
56 template<typename Os, typename In, typename Sz> Os& writeData(wchar_t const* title, In beg, Sz n, Os& os)
59 /* TODO: use tostring_common (with a kind of std::boolalpha for boolean output)
61 mycopy_n(beg, n, std::ostream_iterator<typename std::iterator_traits<In>::value_type, char>(os, L" "));
68 Printer(int precision) : p(precision)
72 std::wstring typeName( /* */) const
78 std::wstring emptyName( /* */) const
84 std::wstring allZeroName( /* */) const
89 std::wstring operator()(T const& t) const
92 std::wostringstream ostr;
101 std::wstring Printer::operator()(bool const& b) const
114 std::wstring Printer::operator()(double const& d) const
116 std::wostringstream ostr;
118 getDoubleFormat(d, &df);
119 addDoubleValue(&ostr, d, &df);
124 std::wstring Printer::operator()(std::complex<double > const& c) const
126 std::wostringstream ostr;
128 DoubleFormat dfR, dfI;
129 getComplexFormat(c.real(), c.imag(), &iLen, &dfR, &dfI);
130 addDoubleComplexValue(&ostr, c.real(), c.imag(), iLen, &dfR, &dfI);
135 std::wstring Printer::typeName<bool>() const
137 return L"sparse boolean";
141 std::wstring Printer::allZeroName<bool>() const
147 std::wstring Printer::emptyName<bool>() const
152 template<typename T> std::wstring toString(T const& m, int precision)
154 std::wostringstream ostr;
158 getIntFormat(m.rows(), &iWidthRows);
159 getIntFormat(m.cols(), &iWidthCols);
162 addIntValue<unsigned long long>(&ostr, m.rows(), iWidthRows);
164 addIntValue<unsigned long long>(&ostr, m.cols(), iWidthCols);
167 Printer p(precision);
168 if (m.rows()*m.cols() ==0)
170 ostr << (p.emptyName<typename Eigen::internal::traits<T>::Scalar>());
172 else if (!m.nonZeros())
174 ostr << (p.allZeroName<typename Eigen::internal::traits<T>::Scalar>());
176 ostr << " " << p.typeName<typename Eigen::internal::traits<T>::Scalar>() << L" matrix\n\n";
178 auto * pIColPos = m.innerIndexPtr();
179 auto * pINbItemByRow = m.outerIndexPtr();
183 int size = static_cast<int>(m.rows() + 1);
184 for (size_t j = 1; j < size; j++)
186 for (size_t i = pINbItemByRow[j - 1]; i < pINbItemByRow[j]; i++)
189 addIntValue<unsigned long long>(&ostr, (int)j, iWidthRows);
191 addIntValue<unsigned long long>(&ostr, pIColPos[iPos] + 1, iWidthCols);
192 ostr << L")\t" << p(m.valuePtr()[iPos]) << std::endl;
201 /** utility function to compare two Eigen::Sparse matrices to equality
203 template<typename T> bool equal(T const& s1, T const& s2)
206 // only compares elts when both inner iterators are "defined", so we assert that we compared all the non zero values
207 // i.e. the inner iterators where defined for the same values
208 std::size_t nbElts(0);
210 for (int k = 0; res && k != s1.outerSize(); ++k)
212 for (typename T::InnerIterator it1(s1, k), it2(s2, k); res && it1 && it2; ++it1, ++it2, ++nbElts)
214 res = (it1.value() == it2.value()
215 && it1.row() == it2.row()
216 && it1.col() == it2.col());
219 return res && (nbElts == s1.nonZeros()) && (nbElts == s2.nonZeros());
222 utility function to set non zero values of an Eigen::Sparse matrix to a fixed values
223 @param s : sparse matrix to modify
224 @param v : value to set (default to 1.)
226 template<typename T> bool setNonZero(T& s, typename Eigen::internal::traits<T>::Scalar v = 1.)
228 for (auto j = 0; j < s.outerSize(); ++j)
230 for (typename T::InnerIterator it(s, j); it; ++it)
240 template<typename Src, typename Sp>
241 void doAppend(Src SPARSE_CONST& src, int r, int c, Sp& dest)
243 typedef typename Eigen::internal::traits<Sp>::Scalar data_t;
244 mycopy_n(makeMatrixIterator<data_t>(src, makeNonZerosIterator(src)), nonZeros(src)
245 , makeMatrixIterator<data_t>(dest, makeTranslatedIterator(makeNonZerosIterator(src), Coords2D(r, c))));
248 template<typename Scalar1, typename Scalar2>
249 void doAppend(Eigen::SparseMatrix<Scalar1, Eigen::RowMajor> SPARSE_CONST& src, int r, int c, Eigen::SparseMatrix<Scalar2, Eigen::RowMajor>& dest)
251 typedef typename Eigen::SparseMatrix<Scalar1, Eigen::RowMajor>::InnerIterator srcIt_t;
252 for (std::size_t k = 0; k != src.outerSize(); ++k)
254 for (srcIt_t it(src, (int)k); it; ++it)
256 if (dest.isCompressed() && dest.coeff(it.row() + r, it.col() + c) == Scalar2(0))
258 dest.reserve(dest.nonZeros() + 1);
261 dest.insert(it.row() + r, it.col() + c) = it.value();
266 Sp is an Eigen::SparseMatrix
268 template<typename Sp, typename M>
269 void cwiseInPlaceProduct(Sp& sp, M SPARSE_CONST& m)
271 // should be a transform_n() over makeNonZerosIterator(src)
272 for (std::size_t k = 0; k != sp.outerSize(); ++k)
274 for (typename Sp::InnerIterator it(sp, k); it; ++it)
276 it.valueRef() *= get<typename Eigen::internal::traits<Sp>::Scalar >(m, it.row(), it.col());
288 inline T& operator()(T& /*x*/, T& y)
295 void getinsertedupdated(T* sp, types::Double* i, types::Double* j, int& updated, int& inserted)
297 int iRowSize = i->getSize();
298 int iColSize = j->getSize();
299 double* pI = i->get();
300 double* pJ = j->get();
305 for (int i = 0; i < iRowSize; i++)
307 for (int j = 0; j < iColSize; j++)
309 auto val = sp->coeff(static_cast<int>(pI[i] - 1), static_cast<int>(pJ[j] - 1));
323 void getinsertedupdated(T* sp, types::Double* i, int& updated, int& inserted)
325 int iSize = i->getSize();
326 double* pIdx = i->get();
327 int rows = static_cast<int>(sp->rows());
332 for (int i = 0; i < iSize; i++)
334 int iRow = static_cast<int>(pIdx[i] - 1) % rows;
335 int iCol = static_cast<int>(pIdx[i] - 1) / rows;
336 auto val = sp->coeff(iRow, iCol);
348 template<typename T, typename Arg>
349 T* create_new(Arg const& a)
355 Double* create_new(double const& d)
357 Double* res(new Double(1, 1, false));
363 Double* create_new(std::complex<double>const& c)
365 Double* res(new Double(1, 1, true));
366 res->set(0, 0, c.real());
367 res->setImg(0, 0, c.imag());
372 Double* create_new(Sparse const& s)
374 Sparse& cs(const_cast<Sparse&>(s)); // inherited member functions are not const-correct
375 Double* res(new Double(cs.getRows(), cs.getCols(), cs.isComplex()));
376 const_cast<Sparse&>(s).fill(*res);
386 Inspector::removeItem(this);
390 Sparse::Sparse(Sparse const& src)
391 : matrixReal(src.matrixReal ? new RealSparse_t(*src.matrixReal) : 0)
392 , matrixCplx(src.matrixCplx ? new CplxSparse_t(*src.matrixCplx) : 0)
395 m_iRows = const_cast<Sparse*>(&src)->getRows();
396 m_iCols = const_cast<Sparse*>(&src)->getCols();
397 m_iSize = m_iRows * m_iCols;
399 m_piDims[0] = m_iRows;
400 m_piDims[1] = m_iCols;
402 Inspector::addItem(this);
406 Sparse::Sparse(int _iRows, int _iCols, bool cplx)
407 : matrixReal(cplx ? 0 : new RealSparse_t(_iRows, _iCols))
408 , matrixCplx(cplx ? new CplxSparse_t(_iRows, _iCols) : 0)
412 m_iSize = _iRows * _iCols;
414 m_piDims[0] = _iRows;
415 m_piDims[1] = _iCols;
417 Inspector::addItem(this);
421 Sparse::Sparse(Double SPARSE_CONST& src)
424 int size = src.getSize();
425 int row = src.getRows();
426 Double* idx = new Double(src.getSize(), 2);
427 double* p = idx->get();
428 for (int i = 0; i < size; ++i)
430 p[i] = (double)(i % row) + 1;
431 p[i + size] = (double)(i / row) + 1;
433 create2(src.getRows(), src.getCols(), src, *idx);
436 Inspector::addItem(this);
440 Sparse::Sparse(Double SPARSE_CONST& src, Double SPARSE_CONST& idx)
442 int idxrow = idx.getRows();
443 int rows = static_cast<int>(*std::max_element(idx.get(), idx.get() + idxrow));
444 int cols = static_cast<int>(*std::max_element(idx.get() + idxrow, idx.get() + idxrow * 2));
446 create2(rows, cols, src, idx);
448 Inspector::removeItem(this);
452 Sparse::Sparse(Double SPARSE_CONST& src, Double SPARSE_CONST& idx, Double SPARSE_CONST& dims)
454 create2(static_cast<int>(dims.get(0)), static_cast<int>(dims.get(1)), src, idx);
456 Inspector::addItem(this);
460 Sparse::Sparse(RealSparse_t* realSp, CplxSparse_t* cplxSp) : matrixReal(realSp), matrixCplx(cplxSp)
464 m_iCols = static_cast<int>(realSp->cols());
465 m_iRows = static_cast<int>(realSp->rows());
469 m_iCols = static_cast<int>(cplxSp->cols());
470 m_iRows = static_cast<int>(cplxSp->rows());
472 m_iSize = m_iCols * m_iRows;
474 m_piDims[0] = m_iRows;
475 m_piDims[1] = m_iCols;
479 Inspector::addItem(this);
483 Sparse::Sparse(Double SPARSE_CONST& xadj, Double SPARSE_CONST& adjncy, Double SPARSE_CONST& src, std::size_t r, std::size_t c)
485 Adjacency a(xadj.get(), adjncy.get());
486 create(static_cast<int>(r), static_cast<int>(c), src, makeIteratorFromVar(a), src.getSize());
488 Inspector::addItem(this);
492 Sparse::Sparse(int rows, int cols, int nonzeros, int* inner, int* outer, double* real, double* img)
499 matrixCplx = new CplxSparse_t(rows, cols);
500 matrixCplx->reserve((int)nonzeros);
501 out = matrixCplx->outerIndexPtr();
502 in = matrixCplx->innerIndexPtr();
503 matrixReal = nullptr;
507 matrixReal = new RealSparse_t(rows, cols);
508 matrixReal->reserve((int)nonzeros);
509 out = matrixReal->outerIndexPtr();
510 in = matrixReal->innerIndexPtr();
511 matrixCplx = nullptr;
514 //update outerIndexPtr
515 memcpy(out, outer, sizeof(int) * (rows + 1));
516 //update innerIndexPtr
517 memcpy(in, inner, sizeof(int) * nonzeros);
521 std::complex<double>* data = matrixCplx->valuePtr();
522 for (int i = 0; i < nonzeros; ++i)
524 data[i] = std::complex<double>(real[i], img[i]);
529 double* data = matrixReal->valuePtr();
530 for (int i = 0; i < nonzeros; ++i)
539 m_iSize = cols * rows;
541 m_piDims[0] = m_iRows;
542 m_piDims[1] = m_iCols;
544 matrixCplx ? matrixCplx->resizeNonZeros(nonzeros) : matrixReal->resizeNonZeros(nonzeros);
549 bool Sparse::getMemory(long long *_piSize, long long* _piSizePlusType)
551 *_piSize = nonZeros() * sizeof(double) * (isComplex() ? 2 : 1);
552 *_piSizePlusType = *_piSize + sizeof(*this);
556 template<typename DestIter>
557 void Sparse::create(int rows, int cols, Double SPARSE_CONST& src, DestIter o, std::size_t n)
561 m_iSize = cols * rows;
563 m_piDims[0] = m_iRows;
564 m_piDims[1] = m_iCols;
569 matrixCplx = new CplxSparse_t(rows, cols);
570 matrixCplx->reserve((int)n);
571 mycopy_n(makeMatrixIterator<std::complex<double> >(src, RowWiseFullIterator(src.getRows(), src.getCols())), n, makeMatrixIterator<std::complex<double> >(*matrixCplx, o));
575 matrixReal = new RealSparse_t(rows, cols);
576 matrixReal->reserve((int)n);
578 mycopy_n(makeMatrixIterator<double >(src, RowWiseFullIterator(src.getRows(), src.getCols())), n
579 , makeMatrixIterator<double>(*matrixReal, o));
584 void Sparse::create2(int rows, int cols, Double SPARSE_CONST& src, Double SPARSE_CONST& idx)
586 int nnz = src.getSize();
587 double* i = idx.get();
588 double* j = i + idx.getRows();
589 double* valR = src.get();
595 std::vector<CplxTriplet_t> tripletList;
596 tripletList.reserve((int)nnz);
598 double* valI = src.getImg();
600 for (int k = 0; k < nnz; ++k)
602 tripletList.emplace_back(static_cast<int>(i[k]) - 1, static_cast<int>(j[k]) - 1, std::complex<double>(valR[k], valI[k]));
605 matrixCplx = new CplxSparse_t(rows, cols);
606 matrixCplx->setFromTriplets(tripletList.begin(), tripletList.end());
607 m_iRows = static_cast<int>(matrixCplx->rows());
608 m_iCols = static_cast<int>(matrixCplx->cols());
614 std::vector<RealTriplet_t> tripletList;
615 tripletList.reserve((int)nnz);
617 for (int k = 0; k < nnz; ++k)
619 tripletList.emplace_back(static_cast<int>(i[k]) - 1, static_cast<int>(j[k]) - 1, valR[k]);
622 matrixReal = new RealSparse_t(rows, cols);
623 matrixReal->setFromTriplets(tripletList.begin(), tripletList.end());
625 m_iRows = static_cast<int>(matrixReal->rows());
626 m_iCols = static_cast<int>(matrixReal->cols());
629 m_iSize = m_iCols * m_iRows;
631 m_piDims[0] = m_iRows;
632 m_piDims[1] = m_iCols;
636 void Sparse::fill(Double& dest, int r, int c) SPARSE_CONST
638 Sparse & cthis(const_cast<Sparse&>(*this));
641 mycopy_n(makeMatrixIterator<std::complex<double> >(*matrixCplx, RowWiseFullIterator(cthis.getRows(), cthis.getCols())), cthis.getSize()
642 , makeMatrixIterator<std::complex<double> >(dest, RowWiseFullIterator(dest.getRows(), dest.getCols(), r, c)));
646 mycopy_n(makeMatrixIterator<double>(*matrixReal, RowWiseFullIterator(cthis.getRows(), cthis.getCols())), cthis.getSize()
647 , makeMatrixIterator<double >(dest, RowWiseFullIterator(dest.getRows(), dest.getCols(), r, c)));
651 Sparse* Sparse::set(int _iRows, int _iCols, std::complex<double> v, bool _bFinalize)
653 if (_iRows >= getRows() || _iCols >= getCols())
658 typedef Sparse* (Sparse::*set_t)(int, int, std::complex<double>, bool);
659 Sparse* pIT = checkRef(this, (set_t)&Sparse::set, _iRows, _iCols, v, _bFinalize);
667 if (matrixReal->isCompressed() && matrixReal->coeff(_iRows, _iCols) == 0)
669 matrixReal->reserve(nonZeros() + 1);
672 matrixReal->coeffRef(_iRows, _iCols) = v.real();
676 if (matrixCplx->isCompressed() && matrixCplx->coeff(_iRows, _iCols) == std::complex<double>(0, 0))
678 matrixCplx->reserve(nonZeros() + 1);
681 matrixCplx->coeffRef(_iRows, _iCols) = v;
691 Sparse* Sparse::set(int _iRows, int _iCols, double _dblReal, bool _bFinalize)
693 if (_iRows >= getRows() || _iCols >= getCols())
698 typedef Sparse* (Sparse::*set_t)(int, int, double, bool);
699 Sparse* pIT = checkRef(this, (set_t)&Sparse::set, _iRows, _iCols, _dblReal, _bFinalize);
707 if (matrixReal->isCompressed() && matrixReal->coeff(_iRows, _iCols) == 0)
709 matrixReal->reserve(nonZeros() + 1);
712 matrixReal->coeffRef(_iRows, _iCols) = _dblReal;
716 if (matrixCplx->isCompressed() && matrixCplx->coeff(_iRows, _iCols) == std::complex<double>(0, 0))
718 matrixCplx->reserve(nonZeros() + 1);
721 matrixCplx->coeffRef(_iRows, _iCols) = std::complex<double>(_dblReal, 0);
733 void Sparse::finalize()
737 matrixCplx->prune(&keepForSparse<std::complex<double> >);
738 matrixCplx->finalize();
742 matrixReal->prune(&keepForSparse<double>);
743 matrixReal->finalize();
748 bool Sparse::neg(InternalType *& out)
750 SparseBool * _out = new SparseBool(getRows(), getCols());
751 types::neg(getRows(), getCols(), matrixReal, _out->matrixBool);
758 bool Sparse::isComplex() const
760 return static_cast<bool>(matrixCplx != NULL);
763 // TODO: should have both a bounds checking and a non-checking interface to elt access
764 double* Sparse::get()
766 if (isComplex() == false)
768 return matrixReal->valuePtr();
774 double Sparse::get(int _iRows, int _iCols) const
776 return getReal(_iRows, _iCols);
779 double Sparse::getReal(int _iRows, int _iCols) const
784 res = matrixReal->coeff(_iRows, _iCols);
788 res = matrixCplx->coeff(_iRows, _iCols).real();
793 std::complex<double>* Sparse::getImg()
797 return matrixCplx->valuePtr();
803 std::complex<double> Sparse::getImg(int _iRows, int _iCols) const
805 std::complex<double> res;
808 res = matrixCplx->coeff(_iRows, _iCols);
812 res = std::complex<double>(matrixReal->coeff(_iRows, _iCols), 0.);
818 void Sparse::whoAmI() SPARSE_CONST
820 std::cout << "types::Sparse";
823 Sparse* Sparse::clone(void)
825 return new Sparse(*this);
828 bool Sparse::zero_set()
832 matrixReal->setZero();
836 matrixCplx->setZero();
842 // TODO: handle precision and line length
843 bool Sparse::toString(std::wostringstream& ostr)
845 int iPrecision = ConfigVariable::getFormatSize();
849 res = ::toString(*matrixReal, iPrecision);
853 res = ::toString(*matrixCplx, iPrecision);
860 Sparse* Sparse::resize(int _iNewRows, int _iNewCols)
862 typedef Sparse* (Sparse::*resize_t)(int, int);
863 Sparse* pIT = checkRef(this, (resize_t)&Sparse::resize, _iNewRows, _iNewCols);
869 if (_iNewRows <= getRows() && _iNewCols <= getCols())
871 //nothing to do: hence we do NOT fail
875 if (((double)_iNewRows) * ((double)_iNewCols) > INT_MAX)
885 matrixReal->conservativeResize(_iNewRows, _iNewCols);
889 matrixCplx->conservativeResize(_iNewRows, _iNewCols);
894 m_iSize = _iNewRows * _iNewCols;
895 m_piDims[0] = m_iRows;
896 m_piDims[1] = m_iCols;
906 // TODO decide if a complex matrix with 0 imag can be == to a real matrix
907 // not true for dense (cf double.cpp)
908 bool Sparse::operator==(const InternalType& it) SPARSE_CONST
910 Sparse* otherSparse = const_cast<Sparse*>(dynamic_cast<Sparse const*>(&it));/* types::GenericType is not const-correct :( */
911 Sparse & cthis(const_cast<Sparse&>(*this));
913 if (otherSparse == NULL)
918 if (otherSparse->getRows() != cthis.getRows())
923 if (otherSparse->getCols() != cthis.getCols())
928 if (otherSparse->isComplex() != isComplex())
935 return equal(*matrixCplx, *otherSparse->matrixCplx);
939 return equal(*matrixReal, *otherSparse->matrixReal);
943 bool Sparse::one_set()
947 return setNonZero(*matrixCplx);
951 return setNonZero(*matrixReal);
955 void Sparse::toComplex()
961 matrixCplx = new CplxSparse_t(matrixReal->cast<std::complex<double> >());
974 GenericType* Sparse::insertNew(typed_list* _pArgs)
979 int iDims = (int)_pArgs->size();
980 int* piMaxDim = new int[iDims];
981 int* piCountDim = new int[iDims];
982 bool bComplex = isComplex();
983 bool bUndefine = false;
985 //evaluate each argument and replace by appropriate value and compute the count of combinations
986 int iSeqCount = checkIndexesArguments(NULL, _pArgs, &pArg, piMaxDim, piCountDim);
990 cleanIndexesArguments(_pArgs, &pArg);
991 return createEmptyDouble();
996 iSeqCount = -iSeqCount;
1002 //manage : and $ in creation by insertion
1004 int *piSourceDims = getDimsArray();
1006 for (int i = 0; i < iDims; i++)
1008 if (pArg[i] == NULL)
1018 piMaxDim[i] = piSourceDims[iSource];
1019 piCountDim[i] = piSourceDims[iSource];
1022 //replace pArg value by the new one
1023 pArg[i] = createDoubleVector(piMaxDim[i]);
1027 // piMaxDim[i] = piCountDim[i];
1032 //remove last dimension at size 1
1033 //remove last dimension if are == 1
1034 for (int i = (iDims - 1); i >= 2; i--)
1036 if (piMaxDim[i] == 1)
1047 if (checkArgValidity(pArg) == false)
1050 cleanIndexesArguments(_pArgs, &pArg);
1051 //contain bad index, like <= 0, ...
1059 pOut = new Sparse(piCountDim[0], 1, bComplex);
1064 pOut = new Sparse(1, piCountDim[0], bComplex);
1069 pOut = new Sparse(piMaxDim[0], piMaxDim[1], bComplex);
1070 //pOut = createEmpty(iDims, piMaxDim, bComplex);
1073 //insert values in new matrix
1074 Sparse* pOut2 = pOut->insert(&pArg, this);
1081 cleanIndexesArguments(_pArgs, &pArg);
1086 Sparse* Sparse::insert(typed_list* _pArgs, InternalType* _pSource)
1088 typedef Sparse* (Sparse::*insert_t)(typed_list*, InternalType*);
1089 Sparse* pIT = checkRef(this, (insert_t)&Sparse::insert, _pArgs, _pSource);
1095 if (_pSource->isSparse())
1097 return insert(_pArgs, _pSource->getAs<Sparse>());
1100 bool bNeedToResize = false;
1101 int iDims = (int)_pArgs->size();
1104 //sparse are only in 2 dims
1110 int* piMaxDim = new int[2];
1111 int* piCountDim = new int[2];
1116 Double* pSource = _pSource->getAs<Double>();
1118 //evaluate each argument and replace by appropriate value and compute the count of combinations
1119 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1123 delete[] piCountDim;
1125 cleanIndexesArguments(_pArgs, &pArg);
1132 if (getRows() == 1 || getCols() == 1)
1135 if (getRows() * getCols() < piMaxDim[0])
1137 bNeedToResize = true;
1139 //need to enlarge sparse dimensions
1140 if (getCols() == 1 || getRows() * getCols() == 0)
1143 iNewRows = piMaxDim[0];
1146 else if (getRows() == 1)
1150 iNewCols = piMaxDim[0];
1154 else if ((size_t)getRows() * (size_t)getCols() < (size_t)piMaxDim[0])
1157 delete[] piCountDim;
1159 cleanIndexesArguments(_pArgs, &pArg);
1166 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
1168 bNeedToResize = true;
1169 iNewRows = std::max(getRows(), piMaxDim[0]);
1170 iNewCols = std::max(getCols(), piMaxDim[1]);
1175 delete[] piCountDim;
1177 //check number of insertion
1178 if (pSource->isScalar() == false && pSource->getSize() != iSeqCount)
1181 cleanIndexesArguments(_pArgs, &pArg);
1185 //now you are sure to be able to insert values
1188 if (resize(iNewRows, iNewCols) == NULL)
1191 cleanIndexesArguments(_pArgs, &pArg);
1197 if (pSource->isComplex() && isComplex() == false)
1202 int rows = getRows();
1203 int cols = getCols();
1205 int nnz = static_cast<int>(nonZeros());
1217 getinsertedupdated(matrixCplx, pArg[0]->getAs<Double>(), pArg[1]->getAs<Double>(), updated, inserted);
1221 getinsertedupdated(matrixReal, pArg[0]->getAs<Double>(), pArg[1]->getAs<Double>(), updated, inserted);
1228 getinsertedupdated(matrixCplx, pArg[0]->getAs<Double>(), updated, inserted);
1232 getinsertedupdated(matrixReal, pArg[0]->getAs<Double>(), updated, inserted);
1236 ratio = (double)inserted / (double)nnz;
1239 if (ratio < 0.05) // less 5%
1241 int nnzFinal = nnz + inserted;
1244 matrixCplx->reserve(nnzFinal);
1248 matrixReal->reserve(nnzFinal);
1253 double* pIdx = pArg[0]->getAs<Double>()->get();
1254 int rows = getRows();
1255 double* pR = pSource->get();
1256 double* pI = pSource->getImg();
1258 for (int i = 0; i < iSeqCount; i++)
1260 int iRow = static_cast<int>(pIdx[i] - 1) % rows;
1261 int iCol = static_cast<int>(pIdx[i] - 1) / rows;
1262 if (pSource->isScalar())
1264 if (pSource->isComplex())
1266 set(iRow, iCol, std::complex<double>(pR[0], pI[0]), false);
1270 set(iRow, iCol, pR[0], false);
1275 if (pSource->isComplex())
1277 set(iRow, iCol, std::complex<double>(pR[i], pI[i]), false);
1281 set(iRow, iCol, pR[i], false);
1288 double* pIdxRow = pArg[0]->getAs<Double>()->get();
1289 int iRowSize = pArg[0]->getAs<Double>()->getSize();
1290 double* pIdxCol = pArg[1]->getAs<Double>()->get();
1291 double* pR = pSource->get();
1292 double* pI = pSource->getImg();
1293 if (pSource->isScalar())
1298 std::complex<double> val(pR[0], pI ? pI[0] : 0);
1299 for (int i = 0; i < iSeqCount; i++)
1301 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, val, false);
1308 for (int i = 0; i < iSeqCount; i++)
1310 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, val, false);
1319 for (int i = 0; i < iSeqCount; i++)
1321 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, std::complex<double>(pR[i], pI ? pI[i] : 0), false);
1327 for (int i = 0; i < iSeqCount; i++)
1329 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, pR[i], false);
1341 std::vector<CplxTriplet_t> tripletList;
1343 double* pIdx = pArg[0]->getAs<Double>()->get();
1344 double* srcR = pSource->get();
1345 double* srcI = NULL;
1347 int incR = pSource->isScalar() ? 0 : 1;
1350 if (pSource->isComplex())
1352 srcI = pSource->getImg();
1353 incI = pSource->isScalar() ? 0 : 1;
1364 std::complex<double>* val = matrixCplx->valuePtr();
1367 for (int k = 0; k < matrixCplx->outerSize(); ++k)
1369 for (CplxSparse_t::InnerIterator it(*matrixCplx, k); it; ++it)
1371 //m[static_cast<size_t>(it.row()) + static_cast<size_t>(it.col()) * rows] = it.value();
1372 tripletList.emplace_back(it.row(), it.col(), it.value());
1376 matrixCplx->setZero();
1379 for (int i = 0; i < iSeqCount; i++)
1381 size_t idx = static_cast<size_t>(pIdx[i] - 1);
1382 int iRow = static_cast<int>(idx % rows);
1383 int iCol = static_cast<int>(idx / rows);
1384 //m[static_cast<size_t>(pIdx[i]) - 1] = std::complex<double>(*srcR, *srcI);
1385 tripletList.emplace_back(iRow, iCol, std::complex<double>(*srcR, *srcI));
1390 matrixCplx->reserve(static_cast<int>(tripletList.size()));
1391 matrixCplx->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<std::complex<double>>());
1396 std::vector<RealTriplet_t> tripletList;
1398 double* pIdx = pArg[0]->getAs<Double>()->get();
1399 double* src = pSource->get();
1400 int inc = pSource->isScalar() ? 0 : 1;
1405 for (int k = 0; k < matrixReal->outerSize(); ++k)
1407 for (RealSparse_t::InnerIterator it(*matrixReal, k); it; ++it)
1409 //m[static_cast<size_t>(it.row()) + static_cast<size_t>(it.col()) * rows] = it.value();
1410 tripletList.emplace_back(it.row(), it.col(), it.value());
1414 matrixReal->setZero();
1417 for (int i = 0; i < iSeqCount; i++)
1419 size_t idx = static_cast<size_t>(pIdx[i] - 1);
1420 int iRow = static_cast<int>(idx % rows);
1421 int iCol = static_cast<int>(idx / rows);
1422 //m[static_cast<size_t>(pIdx[i]) - 1] = *src;
1423 tripletList.emplace_back(iRow, iCol, *src);
1427 matrixReal->reserve(static_cast<int>(tripletList.size()));
1428 matrixReal->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<double>());
1434 int iRowSize = pArg[0]->getAs<Double>()->getSize();
1435 double* pI = pArg[0]->getAs<Double>()->get();
1436 double* pJ = pArg[1]->getAs<Double>()->get();
1440 std::vector<CplxTriplet_t> tripletList;
1441 double* srcR = pSource->get();
1442 double* srcI = NULL;
1444 int incR = pSource->isScalar() ? 0 : 1;
1447 if (pSource->isComplex())
1449 srcI = pSource->getImg();
1450 incI = pSource->isScalar() ? 0 : 1;
1461 for (int k = 0; k < matrixCplx->outerSize(); ++k)
1463 for (CplxSparse_t::InnerIterator it(*matrixCplx, k); it; ++it)
1465 //m[static_cast<size_t>(it.row()) + static_cast<size_t>(it.col()) * rows] = it.value();
1466 tripletList.emplace_back(it.row(), it.col(), it.value());
1470 matrixCplx->setZero();
1474 for (int i = 0; i < iSeqCount; i++)
1476 int iRow = static_cast<int>(i % iRowSize);
1477 int iCol = static_cast<int>(i / iRowSize);
1478 tripletList.emplace_back(static_cast<int>(pI[iRow] - 1), static_cast<int>(pJ[iCol] - 1), std::complex<double>(*srcR, *srcI));
1483 matrixCplx->reserve(static_cast<int>(tripletList.size()));
1484 matrixCplx->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<std::complex<double>>());
1488 std::vector<RealTriplet_t> tripletList;
1489 double* src = pSource->get();
1490 int inc = pSource->isScalar() ? 0 : 1;
1494 double* val = matrixReal->valuePtr();
1497 for (int k = 0; k < matrixReal->outerSize(); ++k)
1499 for (RealSparse_t::InnerIterator it(*matrixReal, k); it; ++it)
1501 //m[static_cast<size_t>(it.row()) + static_cast<size_t>(it.col()) * rows] = it.value();
1502 tripletList.emplace_back(it.row(), it.col(), it.value());
1508 for (int i = 0; i < iSeqCount; ++i)
1510 int iRow = static_cast<int>(i % iRowSize);
1511 int iCol = static_cast<int>(i / iRowSize);
1512 tripletList.emplace_back(static_cast<int>(pI[iRow] - 1) , static_cast<int>(pJ[iCol] - 1) , *src);
1516 matrixReal->setZero();
1517 matrixReal->reserve(static_cast<int>(tripletList.size()));
1518 matrixReal->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<double>());
1526 cleanIndexesArguments(_pArgs, &pArg);
1530 Sparse* Sparse::insert(typed_list* _pArgs, Sparse* _pSource)
1532 bool bNeedToResize = false;
1533 int iDims = (int)_pArgs->size();
1536 //sparse are only in 2 dims
1549 //evaluate each argument and replace by appropriate value and compute the count of combinations
1550 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1554 cleanIndexesArguments(_pArgs, &pArg);
1561 if (getRows() == 1 || getCols() == 1)
1564 bNeedToResize = true;
1565 if (getSize() < piMaxDim[0])
1567 //need to enlarge sparse dimensions
1568 if (getCols() == 1 || getSize() == 0)
1571 iNewRows = piMaxDim[0];
1574 else if (getRows() == 1)
1578 iNewCols = piMaxDim[0];
1582 else if (getSize() < piMaxDim[0])
1585 cleanIndexesArguments(_pArgs, &pArg);
1592 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
1594 bNeedToResize = true;
1595 iNewRows = std::max(getRows(), piMaxDim[0]);
1596 iNewCols = std::max(getCols(), piMaxDim[1]);
1600 //check number of insertion
1601 if (_pSource->isScalar() == false && _pSource->getSize() != iSeqCount)
1604 cleanIndexesArguments(_pArgs, &pArg);
1608 //now you are sure to be able to insert values
1611 if (resize(iNewRows, iNewCols) == NULL)
1614 cleanIndexesArguments(_pArgs, &pArg);
1620 if (_pSource->isComplex() && isComplex() == false)
1627 double* pIdx = pArg[0]->getAs<Double>()->get();
1628 for (int i = 0; i < iSeqCount; i++)
1630 int iRow = static_cast<int>(pIdx[i] - 1) % getRows();
1631 int iCol = static_cast<int>(pIdx[i] - 1) / getRows();
1633 if (_pSource->isScalar())
1635 if (_pSource->isComplex())
1637 set(iRow, iCol, _pSource->getImg(0, 0), false);
1641 set(iRow, iCol, _pSource->get(0, 0), false);
1646 int iRowOrig = i % _pSource->getRows();
1647 int iColOrig = i / _pSource->getRows();
1648 if (_pSource->isComplex())
1650 set(iRow, iCol, _pSource->getImg(iRowOrig, iColOrig), false);
1654 set(iRow, iCol, _pSource->get(iRowOrig, iColOrig), false);
1661 double* pIdxRow = pArg[0]->getAs<Double>()->get();
1662 int iRowSize = pArg[0]->getAs<Double>()->getSize();
1663 double* pIdxCol = pArg[1]->getAs<Double>()->get();
1665 for (int i = 0; i < iSeqCount; i++)
1667 if (_pSource->isScalar())
1669 if (_pSource->isComplex())
1671 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->getImg(0, 0), false);
1675 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(0, 0), false);
1680 int iRowOrig = i % _pSource->getRows();
1681 int iColOrig = i / _pSource->getRows();
1682 if (_pSource->isComplex())
1684 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->getImg(iRowOrig, iColOrig), false);
1688 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(iRowOrig, iColOrig), false);
1697 cleanIndexesArguments(_pArgs, &pArg);
1702 GenericType* Sparse::remove(typed_list* _pArgs)
1704 Sparse* pOut = NULL;
1705 int iDims = (int)_pArgs->size();
1708 //sparse are only in 2 dims
1717 //evaluate each argument and replace by appropriate value and compute the count of combinations
1718 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1722 cleanIndexesArguments(_pArgs, &pArg);
1726 bool* pbFull = new bool[iDims];
1727 //coord must represent all values on a dimension
1728 for (int i = 0; i < iDims; i++)
1731 int iDimToCheck = getVarMaxDim(i, iDims);
1732 int iIndexSize = pArg[i]->getAs<GenericType>()->getSize();
1734 //we can have index more than once
1735 if (iIndexSize >= iDimToCheck)
1737 //size is good, now check datas
1738 double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
1739 for (int j = 0; j < iDimToCheck; j++)
1742 for (int k = 0; k < iIndexSize; k++)
1744 if ((int)pIndexes[k] == j + 1)
1755 //only one dims can be not full/entire
1756 bool bNotEntire = false;
1758 bool bTooMuchNotEntire = false;
1759 for (int i = 0; i < iDims; i++)
1761 if (pbFull[i] == false)
1763 if (bNotEntire == false)
1770 bTooMuchNotEntire = true;
1778 if (bTooMuchNotEntire == true)
1781 cleanIndexesArguments(_pArgs, &pArg);
1785 //find index to keep
1786 int iNotEntireSize = pArg[iNotEntire]->getAs<GenericType>()->getSize();
1787 double* piNotEntireIndex = getDoubleArrayFromDouble(pArg[iNotEntire]);
1788 int iKeepSize = getVarMaxDim(iNotEntire, iDims);
1789 bool* pbKeep = new bool[iKeepSize];
1791 //fill pbKeep with true value
1792 for (int i = 0; i < iKeepSize; i++)
1797 for (int i = 0; i < iNotEntireSize; i++)
1799 int idx = (int)piNotEntireIndex[i] - 1;
1801 //don't care of value out of bounds
1802 if (idx < iKeepSize)
1804 pbKeep[idx] = false;
1808 int iNewDimSize = 0;
1809 for (int i = 0; i < iKeepSize; i++)
1811 if (pbKeep[i] == true)
1818 if (iNewDimSize == 0)
1821 cleanIndexesArguments(_pArgs, &pArg);
1822 return new Sparse(0, 0);
1825 int* piNewDims = new int[iDims];
1826 for (int i = 0; i < iDims; i++)
1828 if (i == iNotEntire)
1830 piNewDims[i] = iNewDimSize;
1834 piNewDims[i] = getVarMaxDim(i, iDims);
1838 //remove last dimension if are == 1
1839 int iOrigDims = iDims;
1840 for (int i = (iDims - 1); i >= 2; i--)
1842 if (piNewDims[i] == 1)
1854 //two cases, depends of original matrix/vector
1855 if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
1857 //special case for row vector
1858 pOut = new Sparse(1, iNewDimSize, isComplex());
1859 //in this case we have to care of 2nd dimension
1864 pOut = new Sparse(iNewDimSize, 1, isComplex());
1869 pOut = new Sparse(piNewDims[0], piNewDims[1], isComplex());
1873 //find a way to copy existing data to new variable ...
1875 int* piIndexes = new int[iOrigDims];
1876 int* piViewDims = new int[iOrigDims];
1877 for (int i = 0; i < iOrigDims; i++)
1879 piViewDims[i] = getVarMaxDim(i, iOrigDims);
1882 for (int i = 0; i < getSize(); i++)
1884 bool bByPass = false;
1885 getIndexesWithDims(i, piIndexes, piViewDims, iOrigDims);
1887 //check if piIndexes use removed indexes
1888 for (int j = 0; j < iNotEntireSize; j++)
1890 if ((piNotEntireIndex[j] - 1) == piIndexes[iNotEntire])
1892 //by pass this value
1898 if (bByPass == false)
1903 pOut->set(iNewPos, getImg(i));
1907 pOut->set(iNewPos, get(i));
1914 delete[] piViewDims;
1917 cleanIndexesArguments(_pArgs, &pArg);
1922 Sparse* Sparse::append(int r, int c, types::Sparse SPARSE_CONST* src)
1924 Sparse* pIT = checkRef(this, &Sparse::append, r, c, src);
1930 // std::wcerr << L"to a sparse of size"<<getRows() << L","<<getCols() << L" should append @"<<r << L","<<c<< "a sparse:"<< src->toString(32,80)<<std::endl;
1931 if (src->isComplex())
1937 if (src->isComplex())
1939 doAppend(*(src->matrixCplx), r, c, *matrixCplx);
1943 doAppend(*(src->matrixReal), r, c, *matrixCplx);
1948 doAppend(*(src->matrixReal), r, c, *matrixReal);
1953 return this; // realloc is meaningless for sparse matrices
1957 * create a new Sparse of dims according to resSize and fill it from currentSparse (along coords)
1959 GenericType* Sparse::extract(typed_list* _pArgs)
1961 Sparse* pOut = NULL;
1962 int iDims = (int)_pArgs->size();
1963 bool bAllColonIndex = true;
1966 for (int i=0; i<iDims; i++)
1968 bAllColonIndex &= (*_pArgs)[i]->isColon();
1973 if (iDims > 1) // a(:,...,:)
1987 this->transpose((types::InternalType *&)pOut);
1991 pOut = new types::Sparse(getRows()*getCols(), 1, isComplex());
1994 CplxSparse_t *sp = pOut->matrixCplx;
1995 sp->reserve(nonZeros());
1997 for (size_t i=0; i<getRows(); ++i)
1999 for (Sparse::CplxSparse_t::InnerIterator it(*matrixCplx, i); it; ++it)
2001 sp->insert(it.col()*getRows() + i, 0) = it.value();
2007 RealSparse_t *sp = pOut->matrixReal;
2008 sp->reserve(nonZeros());
2010 for (size_t i=0; i<getRows(); ++i)
2012 for (Sparse::RealSparse_t::InnerIterator it(*matrixReal, i); it; ++it)
2014 sp->insert(it.col()*getRows() + i, 0) = it.value();
2022 int* piMaxDim = new int[iDims];
2023 int* piCountDim = new int[iDims];
2025 //evaluate each argument and replace by appropriate value and compute the count of combinations
2026 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
2030 cleanIndexesArguments(_pArgs, &pArg);
2031 if (_pArgs->size() == 0)
2035 delete[] piCountDim;
2037 cleanIndexesArguments(_pArgs, &pArg);
2044 delete[] piCountDim;
2046 cleanIndexesArguments(_pArgs, &pArg);
2047 return new types::Sparse(0,0,false);
2053 if (piMaxDim[0] <= getSize())
2057 types::GenericType* pGT = (*_pArgs)[0]->getAs<GenericType>();
2059 if ((*_pArgs)[0]->isColon())
2061 iNewRows = piCountDim[0];
2063 else if ( (!isScalar() && isVector()) && ((*_pArgs)[0]->isImplicitList() || pGT->isVector()) )
2067 iNewCols = piCountDim[0];
2071 iNewRows = piCountDim[0];
2074 else if ((*_pArgs)[0]->isImplicitList())
2076 iNewCols = piCountDim[0];
2080 int *i_piDims = pGT->getDimsArray();
2081 int i_iDims = pGT->getDims();
2084 iNewRows = piCountDim[0];
2088 iNewRows = i_piDims[0];
2089 iNewCols = i_piDims[1];
2093 double* pIdx = pArg[0]->getAs<Double>()->get();
2096 bool bIsReal = true;
2097 std::vector<CplxTriplet_t> tripletList;
2098 std::vector<RealTriplet_t> realTripletList;
2099 int row = getRows();
2100 for (int i = 0; i < iSeqCount; i++)
2102 int iRowRead = static_cast<int>(pIdx[i] - 1) % row;
2103 int iColRead = static_cast<int>(pIdx[i] - 1) / row;
2104 int iRowWrite = i % iNewRows;
2105 int iColWrite = i / iNewRows;
2107 std::complex<double> dbl = getImg(iRowRead, iColRead);
2110 //only non zero values
2111 tripletList.emplace_back(iRowWrite, iColWrite, dbl);
2112 bIsReal &= (dbl.imag() == 0);
2115 realTripletList.emplace_back(iRowWrite, iColWrite, dbl.real());
2121 RealSparse_t* real = new RealSparse_t(iNewRows, iNewCols);
2122 real->setFromTriplets(realTripletList.begin(), realTripletList.end(), DupFunctor<double>());
2123 pOut = new Sparse(real, nullptr);
2127 CplxSparse_t* cplx = new CplxSparse_t(iNewRows, iNewCols);
2128 cplx->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<std::complex<double>>());
2129 pOut = new Sparse(nullptr, cplx);
2134 RealSparse_t* real = new RealSparse_t(iNewRows, iNewCols);
2135 std::vector<RealTriplet_t> tripletList;
2136 int row = getRows();
2137 for (int i = 0; i < iSeqCount; i++)
2139 int iRowRead = static_cast<int>(pIdx[i] - 1) % row;
2140 int iColRead = static_cast<int>(pIdx[i] - 1) / row;
2141 int iRowWrite = i % iNewRows;
2142 int iColWrite = i / iNewRows;
2144 double dbl = get(iRowRead, iColRead);
2147 //only non zero values
2148 tripletList.emplace_back(iRowWrite, iColWrite, dbl);
2152 real->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<double>());
2153 pOut = new Sparse(real, nullptr);
2159 delete[] piCountDim;
2161 cleanIndexesArguments(_pArgs, &pArg);
2167 if (piMaxDim[0] <= getRows() && piMaxDim[1] <= getCols())
2169 double* pIdxRow = pArg[0]->getAs<Double>()->get();
2170 double* pIdxCol = pArg[1]->getAs<Double>()->get();
2172 int iNewRows = pArg[0]->getAs<Double>()->getSize();
2173 int iNewCols = pArg[1]->getAs<Double>()->getSize();
2177 bool bIsReal = true;
2178 std::vector<CplxTriplet_t> tripletList;
2179 std::vector<RealTriplet_t> realTripletList;
2181 for (int iRow = 0; iRow < iNewRows; iRow++)
2183 for (int iCol = 0; iCol < iNewCols; iCol++)
2185 std::complex<double> dbl = getImg((int)pIdxRow[iRow] - 1, (int)pIdxCol[iCol] - 1);
2188 //only non zero values
2189 tripletList.emplace_back(iRow, iCol, dbl);
2190 bIsReal &= (dbl.imag() == 0.);
2193 realTripletList.emplace_back(iRow, iCol, dbl.real());
2200 RealSparse_t* real = new RealSparse_t(iNewRows, iNewCols);
2201 real->setFromTriplets(realTripletList.begin(), realTripletList.end(), DupFunctor<double>());
2202 pOut = new Sparse(real, nullptr);
2206 CplxSparse_t* cplx = new CplxSparse_t(iNewRows, iNewCols);
2207 cplx->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<std::complex<double>>());
2208 pOut = new Sparse(nullptr, cplx);
2213 RealSparse_t* real = new RealSparse_t(iNewRows, iNewCols);
2214 std::vector<RealTriplet_t> tripletList;
2215 for (int iRow = 0; iRow < iNewRows; iRow++)
2217 for (int iCol = 0; iCol < iNewCols; iCol++)
2219 double dbl = get((int)pIdxRow[iRow] - 1, (int)pIdxCol[iCol] - 1);
2222 //only non zero values
2223 tripletList.emplace_back(iRow, iCol, dbl);
2228 real->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<double>());
2229 pOut = new Sparse(real, nullptr);
2235 delete[] piCountDim;
2237 cleanIndexesArguments(_pArgs, &pArg);
2245 delete[] piCountDim;
2247 cleanIndexesArguments(_pArgs, &pArg);
2252 Sparse* Sparse::extract(int nbCoords, int SPARSE_CONST* coords, int SPARSE_CONST* maxCoords, int SPARSE_CONST* resSize, bool asVector) SPARSE_CONST
2254 if ((asVector && maxCoords[0] > getSize()) ||
2255 (asVector == false && maxCoords[0] > getRows()) ||
2256 (asVector == false && maxCoords[1] > getCols()))
2261 bool const cplx(isComplex());
2265 pSp = (getRows() == 1) ? new Sparse(1, resSize[0], cplx) : new Sparse(resSize[0], 1, cplx);
2269 pSp = new Sparse(resSize[0], resSize[1], cplx);
2271 // std::cerr<<"extracted sparse:"<<pSp->getRows()<<", "<<pSp->getCols()<<"seqCount="<<nbCoords<<"maxDim="<<maxCoords[0] <<","<< maxCoords[1]<<std::endl;
2273 ? copyToSparse(*this, Coords<true>(coords, getRows()), nbCoords
2274 , *pSp, RowWiseFullIterator(pSp->getRows(), pSp->getCols()))
2275 : copyToSparse(*this, Coords<false>(coords), nbCoords
2276 , *pSp, RowWiseFullIterator(pSp->getRows(), pSp->getCols()))))
2284 bool Sparse::invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e)
2288 out.push_back(this);
2292 InternalType * _out = extract(&in);
2295 std::wostringstream os;
2296 os << _W("Invalid index.\n");
2297 throw ast::InternalError(os.str(), 999, e.getLocation());
2299 out.push_back(_out);
2306 bool Sparse::isInvokable() const
2311 bool Sparse::hasInvokeOption() const
2316 int Sparse::getInvokeNbIn()
2321 int Sparse::getInvokeNbOut()
2327 coords are Scilab 1-based
2328 extract std::make_pair(coords, asVector), rowIter
2330 template<typename Src, typename SrcTraversal, typename Sz, typename DestTraversal>
2331 bool Sparse::copyToSparse(Src SPARSE_CONST& src, SrcTraversal srcTrav, Sz n, Sparse& sp, DestTraversal destTrav)
2333 if (!(src.isComplex() || sp.isComplex()))
2335 mycopy_n(makeMatrixIterator<double>(src, srcTrav), n
2336 , makeMatrixIterator<double>(*sp.matrixReal, destTrav));
2341 mycopy_n(makeMatrixIterator<std::complex<double> >(src, srcTrav), n
2342 , makeMatrixIterator<std::complex<double> >(*sp.matrixCplx, destTrav));
2349 // GenericType because we might return a Double* for scalar operand
2350 Sparse* Sparse::add(Sparse const& o) const
2352 RealSparse_t* realSp(0);
2353 CplxSparse_t* cplxSp(0);
2354 if (isComplex() == false && o.isComplex() == false)
2357 realSp = new RealSparse_t(*matrixReal + * (o.matrixReal));
2359 else if (isComplex() == false && o.isComplex() == true)
2361 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >() + * (o.matrixCplx));
2363 else if (isComplex() == true && o.isComplex() == false)
2365 cplxSp = new CplxSparse_t(*matrixCplx + o.matrixReal->cast<std::complex<double> >());
2367 else if (isComplex() == true && o.isComplex() == true)
2369 cplxSp = new CplxSparse_t(*matrixCplx + * (o.matrixCplx));
2372 return new Sparse(realSp, cplxSp);
2375 Sparse* Sparse::substract(Sparse const& o) const
2377 RealSparse_t* realSp(0);
2378 CplxSparse_t* cplxSp(0);
2379 if (isComplex() == false && o.isComplex() == false)
2382 realSp = new RealSparse_t(*matrixReal - * (o.matrixReal));
2384 else if (isComplex() == false && o.isComplex() == true)
2387 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >() - * (o.matrixCplx));
2389 else if (isComplex() == true && o.isComplex() == false)
2392 cplxSp = new CplxSparse_t(*matrixCplx - o.matrixReal->cast<std::complex<double> >());
2394 else if (isComplex() == true && o.isComplex() == true)
2397 cplxSp = new CplxSparse_t(*matrixCplx - * (o.matrixCplx));
2400 return new Sparse(realSp, cplxSp);
2403 Sparse* Sparse::multiply(double s) const
2405 return new Sparse(isComplex() ? 0 : new RealSparse_t((*matrixReal)*s)
2406 , isComplex() ? new CplxSparse_t((*matrixCplx)*s) : 0);
2409 Sparse* Sparse::multiply(std::complex<double> s) const
2412 , isComplex() ? new CplxSparse_t((*matrixCplx) * s) : new CplxSparse_t((*matrixReal) * s));
2415 Sparse* Sparse::multiply(Sparse const& o) const
2417 RealSparse_t* realSp(0);
2418 CplxSparse_t* cplxSp(0);
2420 if (isComplex() == false && o.isComplex() == false)
2422 realSp = new RealSparse_t(*matrixReal **(o.matrixReal));
2424 else if (isComplex() == false && o.isComplex() == true)
2426 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >() **(o.matrixCplx));
2428 else if (isComplex() == true && o.isComplex() == false)
2430 cplxSp = new CplxSparse_t(*matrixCplx * o.matrixReal->cast<std::complex<double> >());
2432 else if (isComplex() == true && o.isComplex() == true)
2434 cplxSp = new CplxSparse_t(*matrixCplx **(o.matrixCplx));
2437 return new Sparse(realSp, cplxSp);
2440 Sparse* Sparse::dotMultiply(Sparse SPARSE_CONST& o) const
2442 RealSparse_t* realSp(0);
2443 CplxSparse_t* cplxSp(0);
2444 if (isComplex() == false && o.isComplex() == false)
2446 realSp = new RealSparse_t(matrixReal->cwiseProduct(*(o.matrixReal)));
2448 else if (isComplex() == false && o.isComplex() == true)
2450 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >().cwiseProduct(*(o.matrixCplx)));
2452 else if (isComplex() == true && o.isComplex() == false)
2454 cplxSp = new CplxSparse_t(matrixCplx->cwiseProduct(o.matrixReal->cast<std::complex<double> >()));
2456 else if (isComplex() == true && o.isComplex() == true)
2458 cplxSp = new CplxSparse_t(matrixCplx->cwiseProduct(*(o.matrixCplx)));
2461 return new Sparse(realSp, cplxSp);
2464 Sparse* Sparse::dotDivide(Sparse SPARSE_CONST& o) const
2466 RealSparse_t* realSp(0);
2467 CplxSparse_t* cplxSp(0);
2468 if (isComplex() == false && o.isComplex() == false)
2470 realSp = new RealSparse_t(matrixReal->cwiseQuotient(*(o.matrixReal)));
2472 else if (isComplex() == false && o.isComplex() == true)
2474 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >().cwiseQuotient(*(o.matrixCplx)));
2476 else if (isComplex() == true && o.isComplex() == false)
2478 cplxSp = new CplxSparse_t(matrixCplx->cwiseQuotient(o.matrixReal->cast<std::complex<double> >()));
2480 else if (isComplex() == true && o.isComplex() == true)
2482 cplxSp = new CplxSparse_t(matrixCplx->cwiseQuotient(*(o.matrixCplx)));
2485 return new Sparse(realSp, cplxSp);
2488 int Sparse::newCholLLT(Sparse** _SpPermut, Sparse** _SpFactor) const
2490 typedef Eigen::SparseMatrix<double, Eigen::ColMajor> RealSparseCol_t;
2491 RealSparseCol_t spColMajor = RealSparseCol_t((const RealSparse_t&) * matrixReal);
2493 // Constructs and performs the LLT factorization of sparse
2494 Eigen::SimplicialLLT<RealSparseCol_t> pLLT(spColMajor);
2495 int iInfo = pLLT.info();
2496 if (iInfo != Eigen::Success)
2503 // Get the lower matrix of factorization.
2504 // The new RealSparse_t will be set in Sparse without copy.
2505 *_SpFactor = new Sparse(new RealSparse_t(pLLT.matrixL()), NULL);
2507 // Get the permutation matrix.
2508 Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> p = pLLT.permutationP();
2509 *_SpPermut = new Sparse(static_cast<int>(p.rows()), static_cast<int>(p.cols()));
2510 for (int i = 0; i < p.rows(); i++)
2512 (*_SpPermut)->set(i, p.indices()[i], 1, false);
2515 (*_SpPermut)->finalize();
2520 bool Sparse::transpose(InternalType *& out)
2522 out = new Sparse(matrixReal ? new RealSparse_t(matrixReal->transpose()) : 0, matrixCplx ? new CplxSparse_t(matrixCplx->transpose()) : 0);
2526 bool Sparse::adjoint(InternalType *& out)
2528 out = new Sparse(matrixReal ? new RealSparse_t(matrixReal->adjoint()) : 0, matrixCplx ? new CplxSparse_t(matrixCplx->adjoint()) : 0);
2534 BoolCast(std::complex<double> const& c) : b(c.real() || c.imag()) {}
2535 operator bool() const
2539 operator double() const
2545 Sparse* Sparse::newOnes() const
2547 // result is never cplx
2548 return new Sparse(matrixReal
2549 ? new RealSparse_t(matrixReal->cast<bool>().cast<double>())
2550 : new RealSparse_t(matrixCplx->cast<BoolCast>().cast<double>())
2556 RealCast(std::complex<double> const& c) : b(c.real()) {}
2557 operator bool() const
2561 operator double() const
2567 Sparse* Sparse::newReal() const
2569 return new Sparse(matrixReal
2571 : new RealSparse_t(matrixCplx->cast<RealCast>().cast<double>())
2575 std::size_t Sparse::nonZeros() const
2579 return matrixCplx->nonZeros();
2583 return matrixReal->nonZeros();
2586 std::size_t Sparse::nonZeros(std::size_t r) const
2591 int* piIndex = matrixReal->outerIndexPtr();
2592 res = piIndex[r + 1] - piIndex[r];
2596 int* piIndex = matrixCplx->outerIndexPtr();
2597 res = piIndex[r + 1] - piIndex[r];
2603 int* Sparse::getNbItemByRow(int* _piNbItemByRows)
2605 int* piNbItemByCols = new int[getRows() + 1];
2608 mycopy_n(matrixCplx->outerIndexPtr(), getRows() + 1, piNbItemByCols);
2612 mycopy_n(matrixReal->outerIndexPtr(), getRows() + 1, piNbItemByCols);
2615 for (int i = 0; i < getRows(); i++)
2617 _piNbItemByRows[i] = piNbItemByCols[i + 1] - piNbItemByCols[i];
2620 delete[] piNbItemByCols;
2621 return _piNbItemByRows;
2624 int* Sparse::getColPos(int* _piColPos)
2628 mycopy_n(matrixCplx->innerIndexPtr(), nonZeros(), _piColPos);
2632 mycopy_n(matrixReal->innerIndexPtr(), nonZeros(), _piColPos);
2635 for (size_t i = 0; i < nonZeros(); i++)
2643 int* Sparse::getInnerPtr(int* count)
2648 ret = matrixCplx->innerIndexPtr();
2649 *count = static_cast<int>(matrixCplx->innerSize());
2653 ret = matrixReal->innerIndexPtr();
2654 *count = static_cast<int>(matrixReal->innerSize());
2660 int* Sparse::getOuterPtr(int* count)
2665 ret = matrixCplx->outerIndexPtr();
2666 *count = static_cast<int>(matrixCplx->outerSize());
2670 ret = matrixReal->outerIndexPtr();
2671 *count = static_cast<int>(matrixReal->outerSize());
2679 template<typename S> struct GetReal : std::unary_function<typename S::InnerIterator, double>
2681 double operator()(typename S::InnerIterator it) const
2686 template<> struct GetReal< Eigen::SparseMatrix<std::complex<double >, Eigen::RowMajor > >
2687 : std::unary_function<Sparse::CplxSparse_t::InnerIterator, double>
2689 double operator()(Sparse::CplxSparse_t::InnerIterator it) const
2691 return it.value().real();
2694 template<typename S> struct GetImag : std::unary_function<typename S::InnerIterator, double>
2696 double operator()(typename S::InnerIterator it) const
2698 return it.value().imag();
2701 template<typename S> struct GetRow : std::unary_function<typename S::InnerIterator, int>
2703 int operator()(typename S::InnerIterator it) const
2705 return static_cast<int>(it.row() + 1);
2708 template<typename S> struct GetCol : std::unary_function<typename S::InnerIterator, int>
2710 int operator()(typename S::InnerIterator it) const
2712 return static_cast<int>(it.col() + 1);
2716 template<typename S, typename Out, typename F> Out sparseTransform(S& s, Out o, F f)
2718 int size = static_cast<int>(s.outerSize());
2719 for (std::size_t k(0); k < size; ++k)
2721 for (typename S::InnerIterator it(s, (int)k); it; ++it, ++o)
2730 std::pair<double*, double*> Sparse::outputValues(double* outReal, double* outImag)const
2733 ? std::make_pair(sparseTransform(*matrixReal, outReal, GetReal<RealSparse_t>()), outImag)
2734 : std::make_pair(sparseTransform(*matrixCplx, outReal, GetReal<CplxSparse_t>())
2735 , sparseTransform(*matrixCplx, outImag, GetImag<CplxSparse_t>()));
2738 int* Sparse::outputRowCol(int* out)const
2741 ? sparseTransform(*matrixReal, sparseTransform(*matrixReal, out, GetRow<RealSparse_t>()), GetCol<RealSparse_t>())
2742 : sparseTransform(*matrixCplx, sparseTransform(*matrixCplx, out, GetRow<CplxSparse_t>()), GetCol<CplxSparse_t>());
2744 double* Sparse::outputCols(double* out) const
2748 mycopy_n(matrixCplx->innerIndexPtr(), nonZeros(), out);
2752 mycopy_n(matrixReal->innerIndexPtr(), nonZeros(), out);
2755 return std::transform(out, out, out, std::bind(std::plus<double>(), std::placeholders::_1, 1));
2759 void Sparse::opposite(void)
2763 std::complex<double>* data = matrixCplx->valuePtr();
2764 std::transform(data, data + matrixCplx->nonZeros(), data, std::negate<std::complex<double> >());
2768 double* data = matrixReal->valuePtr();
2769 std::transform(data, data + matrixReal->nonZeros(), data, std::negate<double>());
2773 SparseBool* Sparse::newLessThan(Sparse &o)
2775 //only real values !
2777 //return cwiseOp<std::less>(*this, o);
2778 int rowL = getRows();
2779 int colL = getCols();
2781 int rowR = o.getRows();
2782 int colR = o.getCols();
2783 int row = std::max(rowL, rowR);
2784 int col = std::max(colL, colR);
2786 //create a boolean sparse matrix with dims of sparses
2787 types::SparseBool* ret = new types::SparseBool(row, col);
2788 if (isScalar() && o.isScalar())
2790 double l = get(0, 0);
2791 double r = o.get(0, 0);
2792 ret->set(0, 0, l < r, false);
2794 else if (isScalar())
2796 int nnzR = static_cast<int>(o.nonZeros());
2797 std::vector<int> rowcolR(nnzR * 2, 0);
2798 o.outputRowCol(rowcolR.data());
2800 //compare all items of R with R[0]
2801 double l = get(0, 0);
2805 ret->setTrue(false);
2808 for (int i = 0; i < nnzR; ++i)
2810 double r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
2811 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l < r, false);
2814 else if (o.isScalar())
2816 int nnzL = static_cast<int>(nonZeros());
2817 std::vector<int> rowcolL(nnzL * 2, 0);
2818 outputRowCol(rowcolL.data());
2820 double r = o.get(0, 0);
2826 for (int i = 0; i < nnzL; ++i)
2828 double l = get(rowcolL[i] - 1, rowcolL[i + nnzL] - 1);
2829 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, l < r, false);
2834 int nnzR = static_cast<int>(o.nonZeros());
2835 std::vector<int> rowcolR(nnzR * 2, 0);
2836 o.outputRowCol(rowcolR.data());
2837 int nnzL = static_cast<int>(nonZeros());
2838 std::vector<int> rowcolL(nnzL * 2, 0);
2839 outputRowCol(rowcolL.data());
2840 //set all values to %t
2841 ret->setFalse(false);
2843 for (int i = 0; i < nnzL; ++i)
2845 double l = get(rowcolL[i] - 1, rowcolL[i + nnzL] - 1);
2846 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, l < 0, false);
2850 //set _pR[i] == _pL[i] for each _pR values
2851 for (int i = 0; i < nnzR; ++i)
2853 //get l and r following non zeros value of R
2854 double l = get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
2855 double r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
2856 //set value following non zeros value of R
2857 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l < r, false);
2865 SparseBool* Sparse::newNotEqualTo(Sparse const&o) const
2867 return cwiseOp<std::not_equal_to>(*this, o);
2870 SparseBool* Sparse::newLessOrEqual(Sparse &o)
2872 //only real values !
2874 //return cwiseOp<std::less>(*this, o);
2875 int rowL = getRows();
2876 int colL = getCols();
2878 int rowR = o.getRows();
2879 int colR = o.getCols();
2880 int row = std::max(rowL, rowR);
2881 int col = std::max(colL, colR);
2883 //create a boolean sparse matrix with dims of sparses
2884 types::SparseBool* ret = new types::SparseBool(row, col);
2885 if (isScalar() && o.isScalar())
2887 double l = get(0, 0);
2888 double r = o.get(0, 0);
2889 ret->set(0, 0, l <= r, false);
2891 else if (isScalar())
2893 int nnzR = static_cast<int>(o.nonZeros());
2894 std::vector<int> rowcolR(nnzR * 2, 0);
2895 o.outputRowCol(rowcolR.data());
2897 //compare all items of R with R[0]
2898 double l = get(0, 0);
2902 ret->setTrue(false);
2905 for (int i = 0; i < nnzR; ++i)
2907 double r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
2908 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l <= r, false);
2911 else if (o.isScalar())
2913 int nnzL = static_cast<int>(nonZeros());
2914 std::vector<int> rowcolL(nnzL * 2, 0);
2915 outputRowCol(rowcolL.data());
2917 double r = o.get(0, 0);
2923 for (int i = 0; i < nnzL; ++i)
2925 double l = get(rowcolL[i] - 1, rowcolL[i + nnzL] - 1);
2926 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, l <= r, false);
2931 int nnzR = static_cast<int>(o.nonZeros());
2932 std::vector<int> rowcolR(nnzR * 2, 0);
2933 o.outputRowCol(rowcolR.data());
2934 int nnzL = static_cast<int>(nonZeros());
2935 std::vector<int> rowcolL(nnzL * 2, 0);
2936 outputRowCol(rowcolL.data());
2937 //set all values to %t
2938 ret->setTrue(false);
2940 for (int i = 0; i < nnzL; ++i)
2942 double l = get(rowcolL[i] - 1, rowcolL[i + nnzL] - 1);
2943 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, l <= 0, false);
2947 //set _pR[i] == _pL[i] for each _pR values
2948 for (int i = 0; i < nnzR; ++i)
2950 //get l and r following non zeros value of R
2951 double l = get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
2952 double r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
2953 //set value following non zeros value of R
2954 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l <= r, false);
2962 SparseBool* Sparse::newEqualTo(Sparse &o)
2964 int rowL = getRows();
2965 int colL = getCols();
2967 int rowR = o.getRows();
2968 int colR = o.getCols();
2969 int row = std::max(rowL, rowR);
2970 int col = std::max(colL, colR);
2972 //create a boolean sparse matrix with dims of sparses
2973 types::SparseBool* ret = new types::SparseBool(row, col);
2974 if (isScalar() && o.isScalar())
2976 if (isComplex() || o.isComplex())
2978 std::complex<double> l = getImg(0, 0);
2979 std::complex<double> r = o.getImg(0, 0);
2980 ret->set(0, 0, l == r, false);
2984 double l = get(0, 0);
2985 double r = o.get(0, 0);
2986 ret->set(0, 0, l == r, false);
2989 else if (isScalar())
2991 int nnzR = static_cast<int>(o.nonZeros());
2992 std::vector<int> rowcolR(nnzR * 2, 0);
2993 o.outputRowCol(rowcolR.data());
2995 //compare all items of R with R[0]
2996 if (isComplex() || o.isComplex())
2998 std::complex<double> l = getImg(0, 0);
2999 for (int i = 0; i < nnzR; ++i)
3001 std::complex<double> r = o.getImg(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
3002 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l == r, false);
3007 double l = get(0, 0);
3008 for (int i = 0; i < nnzR; ++i)
3010 double r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
3011 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l == r, false);
3015 else if (o.isScalar())
3017 int nnzL = static_cast<int>(nonZeros());
3018 std::vector<int> rowcolL(nnzL * 2, 0);
3019 outputRowCol(rowcolL.data());
3021 if (isComplex() || o.isComplex())
3023 std::complex<double> r = o.getImg(0, 0);
3024 for (int i = 0; i < nnzL; ++i)
3026 std::complex<double> l = getImg(rowcolL[i] - 1, rowcolL[i + nnzL] - 1);
3027 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, l == r, false);
3032 double r = get(0, 0);
3033 for (int i = 0; i < nnzL; ++i)
3035 double l = get(rowcolL[i] - 1, rowcolL[i + nnzL] - 1);
3036 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, l == r, false);
3042 int nnzR = static_cast<int>(o.nonZeros());
3043 std::vector<int> rowcolR(nnzR * 2, 0);
3044 o.outputRowCol(rowcolR.data());
3045 int nnzL = static_cast<int>(nonZeros());
3046 std::vector<int> rowcolL(nnzL * 2, 0);
3047 outputRowCol(rowcolL.data());
3048 //set all values to %t
3049 ret->setTrue(false);
3050 //set %f in each pL values
3051 for (int i = 0; i < nnzL; ++i)
3053 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, false, false);
3057 //set _pR[i] == _pL[i] for each _pR values
3058 if (isComplex() || o.isComplex())
3060 for (int i = 0; i < nnzR; ++i)
3062 //get l and r following non zeros value of R
3063 std::complex<double> l = getImg(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
3064 std::complex<double> r = o.getImg(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
3065 //set value following non zeros value of R
3066 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l == r, false);
3071 for (int i = 0; i < nnzR; ++i)
3073 //get l and r following non zeros value of R
3074 double l = get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
3075 double r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
3076 //set value following non zeros value of R
3077 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l == r, false);
3086 Sparse* Sparse::reshape(int* _piDims, int _iDims)
3098 pSp = reshape(_piDims[0], iCols);
3104 Sparse* Sparse::reshape(int _iNewRows, int _iNewCols)
3106 typedef Sparse* (Sparse::*reshape_t)(int, int);
3107 Sparse* pIT = checkRef(this, (reshape_t)&Sparse::reshape, _iNewRows, _iNewCols);
3113 if (_iNewRows * _iNewCols != getRows() * getCols())
3124 size_t iNonZeros = nonZeros();
3125 RealSparse_t *newReal = new RealSparse_t(_iNewRows, _iNewCols);
3126 newReal->reserve((int)iNonZeros);
3129 int* pRows = new int[iNonZeros * 2];
3130 outputRowCol(pRows);
3131 int* pCols = pRows + iNonZeros;
3134 double* pNonZeroR = new double[iNonZeros];
3135 outputValues(pNonZeroR, NULL);
3137 std::vector<RealTriplet_t> tripletList;
3138 for (size_t i = 0; i < iNonZeros; i++)
3140 int iCurrentPos = ((int)pCols[i] - 1) * getRows() + ((int)pRows[i] - 1);
3141 tripletList.emplace_back((int)(iCurrentPos % _iNewRows), (int)(iCurrentPos / _iNewRows), pNonZeroR[i]);
3144 newReal->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<double>());
3147 matrixReal = newReal;
3154 size_t iNonZeros = nonZeros();
3155 CplxSparse_t *newCplx = new CplxSparse_t(_iNewRows, _iNewCols);
3156 newCplx->reserve((int)iNonZeros);
3159 int* pRows = new int[iNonZeros * 2];
3160 outputRowCol(pRows);
3161 int* pCols = pRows + iNonZeros;
3164 double* pNonZeroR = new double[iNonZeros];
3165 double* pNonZeroI = new double[iNonZeros];
3166 outputValues(pNonZeroR, pNonZeroI);
3168 std::vector<CplxTriplet_t> tripletList;
3170 for (size_t i = 0; i < iNonZeros; i++)
3172 int iCurrentPos = ((int)pCols[i] - 1) * getRows() + ((int)pRows[i] - 1);
3173 tripletList.emplace_back((int)(iCurrentPos % _iNewRows), (int)(iCurrentPos / _iNewRows), std::complex<double>(pNonZeroR[i], pNonZeroI[i]));
3176 newCplx->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<std::complex<double>>());
3179 matrixCplx = newCplx;
3185 m_iRows = _iNewRows;
3186 m_iCols = _iNewCols;
3187 m_iSize = _iNewRows * _iNewCols;
3190 m_piDims[0] = m_iRows;
3191 m_piDims[1] = m_iCols;
3204 // SparseBool* SparseBool::new
3206 SparseBool::SparseBool(Bool SPARSE_CONST& src)
3209 int size = src.getSize();
3210 int row = src.getRows();
3211 Double* idx = new Double(src.getSize(), 2);
3212 double* p = idx->get();
3213 for (int i = 0; i < size; ++i)
3215 p[i] = (double)(i % row) + 1;
3216 p[i + size] = (double)(i / row) + 1;
3218 create2(src.getRows(), src.getCols(), src, *idx);
3221 Inspector::addItem(this);
3224 /* @param src : Bool matrix to copy into a new sparse matrix
3225 @param idx : Double matrix to use as indexes to get values from the src
3227 SparseBool::SparseBool(Bool SPARSE_CONST& src, Double SPARSE_CONST& idx)
3229 int idxrow = idx.getRows();
3230 int rows = static_cast<int>(*std::max_element(idx.get(), idx.get() + idxrow));
3231 int cols = static_cast<int>(*std::max_element(idx.get() + idxrow, idx.get() + idxrow * 2));
3232 create2(rows, cols, src, idx);
3234 Inspector::addItem(this);
3238 /* @param src : Bool matrix to copy into a new sparse matrix
3239 @param idx : Double matrix to use as indexes to get values from the src
3240 @param dims : Double matrix containing the dimensions of the new matrix
3242 SparseBool::SparseBool(Bool SPARSE_CONST& src, Double SPARSE_CONST& idx, Double SPARSE_CONST& dims)
3244 create2(static_cast<int>(dims.get(0)), static_cast<int>(dims.get(1)), src, idx);
3246 Inspector::addItem(this);
3250 SparseBool::SparseBool(int _iRows, int _iCols) : matrixBool(new BoolSparse_t(_iRows, _iCols))
3254 m_iSize = _iRows * _iCols;
3256 m_piDims[0] = _iRows;
3257 m_piDims[1] = _iCols;
3259 Inspector::addItem(this);
3263 SparseBool::SparseBool(SparseBool const& src) : matrixBool(new BoolSparse_t(*src.matrixBool))
3266 m_iRows = const_cast<SparseBool*>(&src)->getRows();
3267 m_iCols = const_cast<SparseBool*>(&src)->getCols();
3268 m_iSize = m_iRows * m_iCols;
3269 m_piDims[0] = m_iRows;
3270 m_piDims[1] = m_iCols;
3272 Inspector::addItem(this);
3276 SparseBool::SparseBool(BoolSparse_t* src) : matrixBool(src)
3278 m_iRows = static_cast<int>(src->rows());
3279 m_iCols = static_cast<int>(src->cols());
3280 m_iSize = m_iRows * m_iCols;
3282 m_piDims[0] = m_iRows;
3283 m_piDims[1] = m_iCols;
3285 Inspector::addItem(this);
3289 SparseBool::SparseBool(int rows, int cols, int trues, int* inner, int* outer)
3294 matrixBool = new BoolSparse_t(rows, cols);
3295 matrixBool->reserve((int)trues);
3296 out = matrixBool->outerIndexPtr();
3297 in = matrixBool->innerIndexPtr();
3299 //update outerIndexPtr
3300 memcpy(out, outer, sizeof(int) * (rows + 1));
3301 //update innerIndexPtr
3302 memcpy(in, inner, sizeof(int) * trues);
3304 bool* data = matrixBool->valuePtr();
3305 for (int i = 0; i < trues; ++i)
3312 m_iSize = cols * rows;
3314 m_piDims[0] = m_iRows;
3315 m_piDims[1] = m_iCols;
3317 matrixBool->resizeNonZeros(trues);
3320 bool SparseBool::getMemory(long long *_piSize, long long* _piSizePlusType)
3322 *_piSize = nbTrue() * sizeof(bool);
3323 *_piSizePlusType = *_piSize + sizeof(*this);
3327 void SparseBool::create2(int rows, int cols, Bool SPARSE_CONST& src, Double SPARSE_CONST& idx)
3329 int nnz = src.getSize();
3330 double* i = idx.get();
3331 double* j = i + idx.getRows();
3332 int* val = src.get();
3334 std::vector<BoolTriplet_t> tripletList;
3335 tripletList.reserve((int)nnz);
3337 for (int k = 0; k < nnz; ++k)
3339 tripletList.emplace_back(static_cast<int>(i[k]) - 1, static_cast<int>(j[k]) - 1, val[k] == 1);
3342 matrixBool = new BoolSparse_t(rows, cols);
3343 matrixBool->setFromTriplets(tripletList.begin(), tripletList.end());
3345 m_iRows = static_cast<int>(matrixBool->rows());
3346 m_iCols = static_cast<int>(matrixBool->cols());
3347 m_iSize = cols * rows;
3349 m_piDims[0] = m_iRows;
3350 m_piDims[1] = m_iCols;
3354 SparseBool::~SparseBool()
3358 Inspector::removeItem(this);
3362 bool SparseBool::toString(std::wostringstream& ostr)
3364 ostr << ::toString(*matrixBool, 0);
3368 void SparseBool::whoAmI() SPARSE_CONST
3370 std::cout << "types::SparseBool";
3373 SparseBool* SparseBool::clone(void)
3375 return new SparseBool(*this);
3378 SparseBool* SparseBool::resize(int _iNewRows, int _iNewCols)
3380 typedef SparseBool* (SparseBool::*resize_t)(int, int);
3381 SparseBool* pIT = checkRef(this, (resize_t)&SparseBool::resize, _iNewRows, _iNewCols);
3387 if (_iNewRows <= getRows() && _iNewCols <= getCols())
3389 //nothing to do: hence we do NOT fail
3393 if (((double)_iNewRows) * ((double)_iNewCols) > INT_MAX)
3398 SparseBool* res = NULL;
3401 matrixBool->conservativeResize(_iNewRows, _iNewCols);
3403 m_iRows = _iNewRows;
3404 m_iCols = _iNewCols;
3405 m_iSize = _iNewRows * _iNewCols;
3406 m_piDims[0] = m_iRows;
3407 m_piDims[1] = m_iCols;
3418 SparseBool* SparseBool::insert(typed_list* _pArgs, SparseBool* _pSource)
3420 bool bNeedToResize = false;
3421 int iDims = (int)_pArgs->size();
3424 //sparse are only in 2 dims
3430 int* piMaxDim = new int[2];
3431 int* piCountDim = new int[2];
3437 //evaluate each argument and replace by appropriate value and compute the count of combinations
3438 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
3442 delete[] piCountDim;
3444 cleanIndexesArguments(_pArgs, &pArg);
3451 if (getRows() == 1 || getCols() == 1)
3454 if (getRows() * getCols() < piMaxDim[0])
3456 bNeedToResize = true;
3458 //need to enlarge sparse dimensions
3459 if (getCols() == 1 || getSize() == 0)
3462 iNewRows = piMaxDim[0];
3465 else if (getRows() == 1)
3469 iNewCols = piMaxDim[0];
3473 else if (getRows() * getCols() < piMaxDim[0])
3476 delete[] piCountDim;
3478 cleanIndexesArguments(_pArgs, &pArg);
3485 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
3487 bNeedToResize = true;
3488 iNewRows = std::max(getRows(), piMaxDim[0]);
3489 iNewCols = std::max(getCols(), piMaxDim[1]);
3494 delete[] piCountDim;
3496 //check number of insertion
3497 if (_pSource->isScalar() == false && _pSource->getSize() != iSeqCount)
3500 cleanIndexesArguments(_pArgs, &pArg);
3504 //now you are sure to be able to insert values
3507 if (resize(iNewRows, iNewCols) == NULL)
3510 cleanIndexesArguments(_pArgs, &pArg);
3517 double* pIdx = pArg[0]->getAs<Double>()->get();
3518 for (int i = 0; i < iSeqCount; i++)
3520 int iRow = static_cast<int>(pIdx[i] - 1) % getRows();
3521 int iCol = static_cast<int>(pIdx[i] - 1) / getRows();
3523 if (_pSource->isScalar())
3525 set(iRow, iCol, _pSource->get(0, 0), false);
3529 int iRowOrig = i % _pSource->getRows();
3530 int iColOrig = i / _pSource->getRows();
3531 set(iRow, iCol, _pSource->get(iRowOrig, iColOrig), false);
3537 double* pIdxRow = pArg[0]->getAs<Double>()->get();
3538 int iRowSize = pArg[0]->getAs<Double>()->getSize();
3539 double* pIdxCol = pArg[1]->getAs<Double>()->get();
3541 for (int i = 0; i < iSeqCount; i++)
3543 if (_pSource->isScalar())
3545 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(0, 0), false);
3549 int iRowOrig = i % _pSource->getRows();
3550 int iColOrig = i / _pSource->getRows();
3551 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(iRowOrig, iColOrig), false);
3559 cleanIndexesArguments(_pArgs, &pArg);
3564 SparseBool* SparseBool::insert(typed_list* _pArgs, InternalType* _pSource)
3566 typedef SparseBool* (SparseBool::*insert_t)(typed_list*, InternalType*);
3567 SparseBool* pIT = checkRef(this, (insert_t)&SparseBool::insert, _pArgs, _pSource);
3575 if (_pSource->isSparseBool())
3577 return insert(_pArgs, _pSource->getAs<SparseBool>());
3580 bool bNeedToResize = false;
3581 int iDims = (int)_pArgs->size();
3584 //sparse are only in 2 dims
3596 Bool* pSource = _pSource->getAs<Bool>();
3598 //evaluate each argument and replace by appropriate value and compute the count of combinations
3599 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
3603 cleanIndexesArguments(_pArgs, &pArg);
3610 if (getRows() == 1 || getCols() == 1)
3613 bNeedToResize = true;
3614 if (getRows() * getCols() < piMaxDim[0])
3616 //need to enlarge sparse dimensions
3617 if (getCols() == 1 || getRows() * getCols() == 0)
3620 iNewRows = piMaxDim[0];
3623 else if (getRows() == 1)
3627 iNewCols = piMaxDim[0];
3631 else if (getRows() * getCols() < piMaxDim[0])
3634 cleanIndexesArguments(_pArgs, &pArg);
3641 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
3643 bNeedToResize = true;
3644 iNewRows = std::max(getRows(), piMaxDim[0]);
3645 iNewCols = std::max(getCols(), piMaxDim[1]);
3649 //check number of insertion
3650 if (pSource->isScalar() == false && pSource->getSize() != iSeqCount)
3653 cleanIndexesArguments(_pArgs, &pArg);
3657 //now you are sure to be able to insert values
3660 if (resize(iNewRows, iNewCols) == NULL)
3663 cleanIndexesArguments(_pArgs, &pArg);
3670 double* pIdx = pArg[0]->getAs<Double>()->get();
3671 for (int i = 0; i < iSeqCount; i++)
3673 int iRow = static_cast<int>(pIdx[i] - 1) % getRows();
3674 int iCol = static_cast<int>(pIdx[i] - 1) / getRows();
3675 if (pSource->isScalar())
3677 set(iRow, iCol, pSource->get(0) != 0, false);
3681 set(iRow, iCol, pSource->get(i) != 0, false);
3687 double* pIdxRow = pArg[0]->getAs<Double>()->get();
3688 int iRowSize = pArg[0]->getAs<Double>()->getSize();
3689 double* pIdxCol = pArg[1]->getAs<Double>()->get();
3691 for (int i = 0; i < iSeqCount; i++)
3693 if (pSource->isScalar())
3695 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, pSource->get(0) != 0, false);
3699 int iRowOrig = i % pSource->getRows();
3700 int iColOrig = i / pSource->getRows();
3702 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, pSource->get(iRowOrig, iColOrig) != 0, false);
3710 cleanIndexesArguments(_pArgs, &pArg);
3714 GenericType* SparseBool::remove(typed_list* _pArgs)
3716 SparseBool* pOut = NULL;
3717 int iDims = (int)_pArgs->size();
3720 //sparse are only in 2 dims
3729 //evaluate each argument and replace by appropriate value and compute the count of combinations
3730 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
3734 cleanIndexesArguments(_pArgs, &pArg);
3738 bool* pbFull = new bool[iDims];
3739 //coord must represent all values on a dimension
3740 for (int i = 0; i < iDims; i++)
3743 int iDimToCheck = getVarMaxDim(i, iDims);
3744 int iIndexSize = pArg[i]->getAs<GenericType>()->getSize();
3746 //we can have index more than once
3747 if (iIndexSize >= iDimToCheck)
3749 //size is good, now check datas
3750 double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
3751 for (int j = 0; j < iDimToCheck; j++)
3754 for (int k = 0; k < iIndexSize; k++)
3756 if ((int)pIndexes[k] == j + 1)
3767 //only one dims can be not full/entire
3768 bool bNotEntire = false;
3770 bool bTooMuchNotEntire = false;
3771 for (int i = 0; i < iDims; i++)
3773 if (pbFull[i] == false)
3775 if (bNotEntire == false)
3782 bTooMuchNotEntire = true;
3790 if (bTooMuchNotEntire == true)
3793 cleanIndexesArguments(_pArgs, &pArg);
3797 //find index to keep
3798 int iNotEntireSize = pArg[iNotEntire]->getAs<GenericType>()->getSize();
3799 double* piNotEntireIndex = getDoubleArrayFromDouble(pArg[iNotEntire]);
3800 int iKeepSize = getVarMaxDim(iNotEntire, iDims);
3801 bool* pbKeep = new bool[iKeepSize];
3803 //fill pbKeep with true value
3804 for (int i = 0; i < iKeepSize; i++)
3809 for (int i = 0; i < iNotEntireSize; i++)
3811 int idx = (int)piNotEntireIndex[i] - 1;
3813 //don't care of value out of bounds
3814 if (idx < iKeepSize)
3816 pbKeep[idx] = false;
3820 int iNewDimSize = 0;
3821 for (int i = 0; i < iKeepSize; i++)
3823 if (pbKeep[i] == true)
3830 if (iNewDimSize == 0)
3833 cleanIndexesArguments(_pArgs, &pArg);
3834 return new SparseBool(0, 0);
3837 int* piNewDims = new int[iDims];
3838 for (int i = 0; i < iDims; i++)
3840 if (i == iNotEntire)
3842 piNewDims[i] = iNewDimSize;
3846 piNewDims[i] = getVarMaxDim(i, iDims);
3850 //remove last dimension if are == 1
3851 int iOrigDims = iDims;
3852 for (int i = (iDims - 1); i >= 2; i--)
3854 if (piNewDims[i] == 1)
3866 //two cases, depends of original matrix/vector
3867 if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
3869 //special case for row vector
3870 pOut = new SparseBool(1, iNewDimSize);
3871 //in this case we have to care of 2nd dimension
3876 pOut = new SparseBool(iNewDimSize, 1);
3881 pOut = new SparseBool(piNewDims[0], piNewDims[1]);
3885 //find a way to copy existing data to new variable ...
3887 int* piIndexes = new int[iOrigDims];
3888 int* piViewDims = new int[iOrigDims];
3889 for (int i = 0; i < iOrigDims; i++)
3891 piViewDims[i] = getVarMaxDim(i, iOrigDims);
3894 for (int i = 0; i < getSize(); i++)
3896 bool bByPass = false;
3897 getIndexesWithDims(i, piIndexes, piViewDims, iOrigDims);
3899 //check if piIndexes use removed indexes
3900 for (int j = 0; j < iNotEntireSize; j++)
3902 if ((piNotEntireIndex[j] - 1) == piIndexes[iNotEntire])
3904 //by pass this value
3910 if (bByPass == false)
3913 pOut->set(iNewPos, get(i));
3919 delete[] piViewDims;
3922 cleanIndexesArguments(_pArgs, &pArg);
3927 SparseBool* SparseBool::append(int r, int c, SparseBool SPARSE_CONST* src)
3929 SparseBool* pIT = checkRef(this, &SparseBool::append, r, c, src);
3935 doAppend(*src, r, c, *matrixBool);
3940 GenericType* SparseBool::insertNew(typed_list* _pArgs)
3943 SparseBool *pOut = NULL;
3945 int iDims = (int)_pArgs->size();
3946 int* piMaxDim = new int[iDims];
3947 int* piCountDim = new int[iDims];
3948 bool bUndefine = false;
3950 //evaluate each argument and replace by appropriate value and compute the count of combinations
3951 int iSeqCount = checkIndexesArguments(NULL, _pArgs, &pArg, piMaxDim, piCountDim);
3955 cleanIndexesArguments(_pArgs, &pArg);
3956 return createEmptyDouble();
3961 iSeqCount = -iSeqCount;
3967 //manage : and $ in creation by insertion
3969 int *piSourceDims = getDimsArray();
3971 for (int i = 0; i < iDims; i++)
3973 if (pArg[i] == NULL)
3983 piMaxDim[i] = piSourceDims[iSource];
3984 piCountDim[i] = piSourceDims[iSource];
3987 //replace pArg value by the new one
3988 pArg[i] = createDoubleVector(piMaxDim[i]);
3992 // piMaxDim[i] = piCountDim[i];
3997 //remove last dimension at size 1
3998 //remove last dimension if are == 1
3999 for (int i = (iDims - 1); i >= 2; i--)
4001 if (piMaxDim[i] == 1)
4012 if (checkArgValidity(pArg) == false)
4015 cleanIndexesArguments(_pArgs, &pArg);
4016 //contain bad index, like <= 0, ...
4024 pOut = new SparseBool(piCountDim[0], 1);
4029 pOut = new SparseBool(1, piCountDim[0]);
4034 pOut = new SparseBool(piMaxDim[0], piMaxDim[1]);
4037 //insert values in new matrix
4038 SparseBool* pOut2 = pOut->insert(&pArg, this);
4045 cleanIndexesArguments(_pArgs, &pArg);
4050 SparseBool* SparseBool::extract(int nbCoords, int SPARSE_CONST* coords, int SPARSE_CONST* maxCoords, int SPARSE_CONST* resSize, bool asVector) SPARSE_CONST
4052 if ((asVector && maxCoords[0] > getSize()) ||
4053 (asVector == false && maxCoords[0] > getRows()) ||
4054 (asVector == false && maxCoords[1] > getCols()))
4059 SparseBool * pSp(0);
4062 pSp = (getRows() == 1) ? new SparseBool(1, resSize[0]) : new SparseBool(resSize[0], 1);
4063 mycopy_n(makeMatrixIterator<bool>(*this, Coords<true>(coords, getRows())), nbCoords
4064 , makeMatrixIterator<bool>(*(pSp->matrixBool), RowWiseFullIterator(pSp->getRows(), pSp->getCols())));
4068 pSp = new SparseBool(resSize[0], resSize[1]);
4069 mycopy_n(makeMatrixIterator<bool>(*this, Coords<false>(coords, getRows())), nbCoords
4070 , makeMatrixIterator<bool>(*(pSp->matrixBool), RowWiseFullIterator(pSp->getRows(), pSp->getCols())));
4077 * create a new SparseBool of dims according to resSize and fill it from currentSparseBool (along coords)
4079 GenericType* SparseBool::extract(typed_list* _pArgs)
4081 SparseBool* pOut = NULL;
4082 int iDims = (int)_pArgs->size();
4085 int* piMaxDim = new int[iDims];
4086 int* piCountDim = new int[iDims];
4088 //evaluate each argument and replace by appropriate value and compute the count of combinations
4089 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
4093 cleanIndexesArguments(_pArgs, &pArg);
4094 if (_pArgs->size() == 0)
4097 delete[] piCountDim;
4104 delete[] piCountDim;
4106 return new types::SparseBool(0,0);
4112 // Check that we stay inside the input size.
4113 if (piMaxDim[0] <= getSize())
4118 if ((*_pArgs)[0]->isColon())
4120 iNewRows = piCountDim[0];
4122 else if ( (!isScalar() && isVector()) && ((*_pArgs)[0]->isImplicitList() || (*_pArgs)[0]->getAs<GenericType>()->isVector()) )
4126 iNewCols = piCountDim[0];
4130 iNewRows = piCountDim[0];
4133 else if ((*_pArgs)[0]->isImplicitList())
4135 iNewCols = piCountDim[0];
4139 int *i_piDims = (*_pArgs)[0]->getAs<GenericType>()->getDimsArray();
4140 int i_iDims = (*_pArgs)[0]->getAs<GenericType>()->getDims();
4143 iNewRows = piCountDim[0];
4147 iNewRows = i_piDims[0];
4148 iNewCols = i_piDims[1];
4152 pOut = new SparseBool(iNewRows, iNewCols);
4153 double* pIdx = pArg[0]->getAs<Double>()->get();
4154 // Write in output all elements extract from input.
4155 for (int i = 0; i < iSeqCount; i++)
4163 int iRowRead = static_cast<int>(pIdx[i] - 1) % getRows();
4164 int iColRead = static_cast<int>(pIdx[i] - 1) / getRows();
4166 int iRowWrite = static_cast<int>(i) % iNewRows;
4167 int iColWrite = static_cast<int>(i) / iNewRows;
4169 bool bValue = get(iRowRead, iColRead);
4172 //only non zero values
4173 pOut->set(iRowWrite, iColWrite, true, false);
4180 delete[] piCountDim;
4182 cleanIndexesArguments(_pArgs, &pArg);
4188 // Check that we stay inside the input size.
4189 if (piMaxDim[0] <= getRows() && piMaxDim[1] <= getCols())
4191 double* pIdxRow = pArg[0]->getAs<Double>()->get();
4192 double* pIdxCol = pArg[1]->getAs<Double>()->get();
4194 int iNewRows = pArg[0]->getAs<Double>()->getSize();
4195 int iNewCols = pArg[1]->getAs<Double>()->getSize();
4197 pOut = new SparseBool(iNewRows, iNewCols);
4200 // Write in output all elements extract from input.
4201 for (int iRow = 0; iRow < iNewRows; iRow++)
4203 for (int iCol = 0; iCol < iNewCols; iCol++)
4205 if ((pIdxRow[iRow] < 1) || (pIdxCol[iCol] < 1))
4210 delete[] piCountDim;
4212 cleanIndexesArguments(_pArgs, &pArg);
4215 bool bValue = get((int)pIdxRow[iRow] - 1, (int)pIdxCol[iCol] - 1);
4218 //only non zero values
4219 pOut->set(iRow, iCol, true, false);
4228 delete[] piCountDim;
4230 cleanIndexesArguments(_pArgs, &pArg);
4241 delete[] piCountDim;
4243 cleanIndexesArguments(_pArgs, &pArg);
4248 bool SparseBool::invoke(typed_list & in, optional_list &/*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e)
4252 out.push_back(this);
4256 InternalType * _out = extract(&in);
4259 std::wostringstream os;
4260 os << _W("Invalid index.\n");
4261 throw ast::InternalError(os.str(), 999, e.getLocation());
4263 out.push_back(_out);
4269 bool SparseBool::isInvokable() const
4274 bool SparseBool::hasInvokeOption() const
4279 int SparseBool::getInvokeNbIn()
4284 int SparseBool::getInvokeNbOut()
4289 std::size_t SparseBool::nbTrue() const
4291 return matrixBool->nonZeros();
4293 std::size_t SparseBool::nbTrue(std::size_t r) const
4295 int* piIndex = matrixBool->outerIndexPtr();
4296 return piIndex[r + 1] - piIndex[r];
4300 void SparseBool::setTrue(bool finalize)
4302 int rows = getRows();
4303 int cols = getCols();
4305 std::vector<BoolTriplet_t> tripletList;
4307 for (int i = 0; i < rows; ++i)
4309 for (int j = 0; j < cols; ++j)
4311 tripletList.emplace_back(i, j, true);
4315 matrixBool->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<bool>());
4319 matrixBool->finalize();
4323 void SparseBool::setFalse(bool finalize)
4325 int rows = getRows();
4326 int cols = getCols();
4328 std::vector<BoolTriplet_t> tripletList;
4330 for (int i = 0; i < rows; ++i)
4332 for (int j = 0; j < cols; ++j)
4334 tripletList.emplace_back(i, j, false);
4338 matrixBool->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<bool>());
4342 matrixBool->finalize();
4346 int* SparseBool::getNbItemByRow(int* _piNbItemByRows)
4348 int* piNbItemByRows = new int[getRows() + 1];
4349 mycopy_n(matrixBool->outerIndexPtr(), getRows() + 1, piNbItemByRows);
4351 for (int i = 0; i < getRows(); i++)
4353 _piNbItemByRows[i] = piNbItemByRows[i + 1] - piNbItemByRows[i];
4356 delete[] piNbItemByRows;
4357 return _piNbItemByRows;
4360 int* SparseBool::getColPos(int* _piColPos)
4362 mycopy_n(matrixBool->innerIndexPtr(), nbTrue(), _piColPos);
4363 for (size_t i = 0; i < nbTrue(); i++)
4371 int* SparseBool::outputRowCol(int* out)const
4373 return sparseTransform(*matrixBool, sparseTransform(*matrixBool, out, GetRow<BoolSparse_t>()), GetCol<BoolSparse_t>());
4376 int* SparseBool::getInnerPtr(int* count)
4378 *count = static_cast<int>(matrixBool->innerSize());
4379 return matrixBool->innerIndexPtr();
4382 int* SparseBool::getOuterPtr(int* count)
4384 *count = static_cast<int>(matrixBool->outerSize());
4385 return matrixBool->outerIndexPtr();
4389 bool SparseBool::operator==(const InternalType& it) SPARSE_CONST
4391 SparseBool* otherSparse = const_cast<SparseBool*>(dynamic_cast<SparseBool const*>(&it));/* types::GenericType is not const-correct :( */
4393 && (otherSparse->getRows() == getRows())
4394 && (otherSparse->getCols() == getCols())
4395 && equal(*matrixBool, *otherSparse->matrixBool));
4398 bool SparseBool::operator!=(const InternalType& it) SPARSE_CONST
4400 return !(*this == it);
4403 void SparseBool::finalize()
4405 matrixBool->prune(&keepForSparse<bool>);
4406 matrixBool->finalize();
4409 bool SparseBool::get(int r, int c) SPARSE_CONST
4411 return matrixBool->coeff(r, c);
4414 SparseBool* SparseBool::set(int _iRows, int _iCols, bool _bVal, bool _bFinalize) SPARSE_CONST
4416 typedef SparseBool* (SparseBool::*set_t)(int, int, bool, bool);
4417 SparseBool* pIT = checkRef(this, (set_t)&SparseBool::set, _iRows, _iCols, _bVal, _bFinalize);
4423 if (matrixBool->isCompressed() && matrixBool->coeff(_iRows, _iCols) == false)
4425 matrixBool->reserve(1);
4428 matrixBool->coeffRef(_iRows, _iCols) = _bVal;
4438 void SparseBool::fill(Bool& dest, int r, int c) SPARSE_CONST
4440 mycopy_n(makeMatrixIterator<bool >(*matrixBool, RowWiseFullIterator(getRows(), getCols())), getSize()
4441 , makeMatrixIterator<bool >(dest, RowWiseFullIterator(dest.getRows(), dest.getCols(), r, c)));
4444 Sparse* SparseBool::newOnes() const
4446 return new Sparse(new types::Sparse::RealSparse_t(matrixBool->cast<double>()), 0);
4449 SparseBool* SparseBool::newNotEqualTo(SparseBool const&o) const
4451 return cwiseOp<std::not_equal_to>(*this, o);
4454 SparseBool* SparseBool::newEqualTo(SparseBool& o)
4456 int rowL = getRows();
4457 int colL = getCols();
4459 int rowR = o.getRows();
4460 int colR = o.getCols();
4461 int row = std::max(rowL, rowR);
4462 int col = std::max(colL, colR);
4464 //create a boolean sparse matrix with dims of sparses
4465 types::SparseBool* ret = new types::SparseBool(row, col);
4467 if (isScalar() && o.isScalar())
4470 bool r = o.get(0, 0);
4471 ret->set(0, 0, l == r, false);
4473 else if (isScalar())
4475 int nnzR = static_cast<int>(o.nbTrue());
4476 std::vector<int> rowcolR(nnzR * 2, 0);
4477 o.outputRowCol(rowcolR.data());
4479 //compare all items of R with R[0]
4481 for (int i = 0; i < nnzR; ++i)
4483 bool r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
4484 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l == r, false);
4487 else if (o.isScalar())
4489 int nnzL = static_cast<int>(nbTrue());
4490 std::vector<int> rowcolL(nnzL * 2, 0);
4491 outputRowCol(rowcolL.data());
4494 for (int i = 0; i < nnzL; ++i)
4496 bool l = get(rowcolL[i] - 1, rowcolL[i + nnzL] - 1);
4497 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, l == r, false);
4502 int nnzR = static_cast<int>(o.nbTrue());
4503 std::vector<int> rowcolR(nnzR * 2, 0);
4504 o.outputRowCol(rowcolR.data());
4505 int nnzL = static_cast<int>(nbTrue());
4506 std::vector<int> rowcolL(nnzL * 2, 0);
4507 outputRowCol(rowcolL.data());
4508 //set all values to %t
4509 ret->setTrue(false);
4510 //set %f in each pL values
4511 for (int i = 0; i < nnzL; ++i)
4513 ret->set(rowcolL[i] - 1, rowcolL[i + nnzL] - 1, false, false);
4517 //set _pR[i] == _pL[i] for each _pR values
4518 for (int i = 0; i < nnzR; ++i)
4520 //get l and r following non zeros value of R
4521 bool l = get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
4522 bool r = o.get(rowcolR[i] - 1, rowcolR[i + nnzR] - 1);
4523 //set value following non zeros value of R
4524 ret->set(rowcolR[i] - 1, rowcolR[i + nnzR] - 1, l == r, false);
4532 SparseBool* SparseBool::newLogicalOr(SparseBool const&o) const
4534 return cwiseOp<std::logical_or>(*this, o);
4537 SparseBool* SparseBool::newLogicalAnd(SparseBool const&o) const
4539 return cwiseOp<std::logical_and>(*this, o);
4542 SparseBool* SparseBool::reshape(int* _piDims, int _iDims)
4544 SparseBool* pSpBool = NULL;
4554 pSpBool = reshape(_piDims[0], iCols);
4560 SparseBool* SparseBool::reshape(int _iNewRows, int _iNewCols)
4562 typedef SparseBool* (SparseBool::*reshape_t)(int, int);
4563 SparseBool* pIT = checkRef(this, (reshape_t)&SparseBool::reshape, _iNewRows, _iNewCols);
4569 if (_iNewRows * _iNewCols != getRows() * getCols())
4574 SparseBool* res = NULL;
4578 size_t iNonZeros = matrixBool->nonZeros();
4579 BoolSparse_t *newBool = new BoolSparse_t(_iNewRows, _iNewCols);
4580 newBool->reserve((int)iNonZeros);
4583 int* pRows = new int[iNonZeros * 2];
4584 outputRowCol(pRows);
4585 int* pCols = pRows + iNonZeros;
4587 std::vector<BoolTriplet_t> tripletList;
4589 for (size_t i = 0; i < iNonZeros; i++)
4591 int iCurrentPos = ((int)pCols[i] - 1) * getRows() + ((int)pRows[i] - 1);
4592 tripletList.emplace_back((int)(iCurrentPos % _iNewRows), (int)(iCurrentPos / _iNewRows), true);
4595 newBool->setFromTriplets(tripletList.begin(), tripletList.end(), DupFunctor<bool>());
4598 matrixBool = newBool;
4601 m_iRows = _iNewRows;
4602 m_iCols = _iNewCols;
4603 m_iSize = _iNewRows * _iNewCols;
4606 m_piDims[0] = m_iRows;
4607 m_piDims[1] = m_iCols;
4620 bool SparseBool::transpose(InternalType *& out)
4622 out = new SparseBool(new BoolSparse_t(matrixBool->transpose()));
4626 template<typename T>
4627 void neg(const int r, const int c, const T * const in, Eigen::SparseMatrix<bool, 1> * const out)
4629 for (int i = 0; i < r; i++)
4631 for (int j = 0; j < c; j++)
4633 out->coeffRef(i, j) = !in->coeff(i, j);
4637 out->prune(&keepForSparse<bool>);