2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Bernard HUGUENEY
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
20 #include "tostring_common.hxx"
22 #include "matrixiterator.hxx"
23 #include "types_substraction.hxx"
24 #include "types_addition.hxx"
25 #include "types_multiplication.hxx"
26 #include "formatmode.h"
28 #include "sparseOp.hxx"
31 #include "elem_common.h"
40 /* used for debuging output
42 template<typename Os, typename In, typename Sz> Os& writeData(wchar_t const* title, In beg, Sz n, Os& os)
45 /* TODO: use tostring_common (with a kind of std::boolalpha for boolean output)
47 mycopy_n(beg, n, std::ostream_iterator<typename std::iterator_traits<In>::value_type, char>(os, L" "));
54 Printer (int precision) : p(precision)
58 std::wstring emptyName( /* */) const
64 std::wstring operator()(T const& t) const
67 std::wostringstream ostr;
76 std::wstring Printer::operator()(bool const& b) const
89 std::wstring Printer::operator()(double const& d) const
91 std::wostringstream ostr;
93 getDoubleFormat(d, &df);
94 addDoubleValue(&ostr, d, &df);
99 std::wstring Printer::operator()(std::complex<double > const& c) const
101 std::wostringstream ostr;
103 DoubleFormat dfR, dfI;
104 getComplexFormat(c.real(), c.imag(), &iLen, &dfR, &dfI);
105 addDoubleComplexValue(&ostr, c.real(), c.imag(), iLen, &dfR, &dfI);
110 std::wstring Printer::emptyName<bool>() const
116 template<typename T> std::wstring toString(T const& m, int precision)
118 std::wostringstream ostr;
123 getSignedIntFormat(m.rows(), &iWidthRows);
124 getSignedIntFormat(m.cols(), &iWidthCols);
127 addUnsignedIntValue<unsigned long long>(&ostr, m.rows(), iWidthRows);
129 addUnsignedIntValue<unsigned long long>(&ostr, m.cols(), iWidthCols);
132 Printer p(precision);
135 ostr << ( p.emptyName<typename Eigen::internal::traits<T>::Scalar>());
137 ostr << L" sparse matrix\n\n";
139 const typename Eigen::internal::traits<T>::Index* pInner = m.innerIndexPtr();
140 const typename Eigen::internal::traits<T>::Index* pOuter = m.outerIndexPtr();
145 for (size_t j = 0 ; j < m.rows() ; j++)
148 for (size_t i = 0 ; i < m.nonZeros() ; i++)
153 for (size_t k = 0 ; k < m.outerSize() + 1; k++)
163 addUnsignedIntValue<unsigned long long>(&ostr, iRow + 1, iWidthRows);
165 addUnsignedIntValue<unsigned long long>(&ostr, iCol, iWidthCols);
166 ostr << L")\t" << p(m.valuePtr()[i]) << std::endl;
174 /** utility function to compare two Eigen::Sparse matrices to equality
176 template<typename T> bool equal(T const& s1, T const& s2)
179 // only compares elts when both inner iterators are "defined", so we assert that we compared all the non zero values
180 // i.e. the inner iterators where defined for the same values
181 std::size_t nbElts(0);
183 for (int k = 0; res && k != s1.outerSize(); ++k)
185 for (typename T::InnerIterator it1(s1, k), it2(s2, k); res && it1 && it2 ; ++it1, ++it2, ++nbElts)
187 res = (it1.value() == it2.value()
188 && it1.row() == it2.row()
189 && it1.col() == it2.col());
192 return res && (nbElts == s1.nonZeros()) && (nbElts == s2.nonZeros());
195 utility function to set non zero values of an Eigen::Sparse matrix to a fixed values
196 @param s : sparse matrix to modify
197 @param v : value to set (default to 1.)
199 template<typename T> bool setNonZero(T& s, typename Eigen::internal::traits<T>::Scalar v = 1.)
201 for (typename Eigen::internal::traits<T>::Index j = 0; j < s.outerSize(); ++j)
203 for (typename T::InnerIterator it(s, j); it; ++it)
213 template<typename Src, typename Sp>
214 void doAppend(Src CONST& src, int r, int c, Sp& dest)
216 typedef typename Eigen::internal::traits<Sp>::Scalar data_t;
217 mycopy_n(makeMatrixIterator<data_t>(src, makeNonZerosIterator(src)), nonZeros(src)
218 , makeMatrixIterator<data_t>(dest, makeTranslatedIterator(makeNonZerosIterator(src), Coords2D(r, c))));
221 // TODO : awaiting ggael's response to bug for [sp, sp]
222 template<typename Scalar1, typename Scalar2>
223 void doAppend(Eigen::SparseMatrix<Scalar1> CONST& src, int r, int c, Eigen::SparseMatrix<Scalar2>& dest)
225 typedef typename Eigen::SparseMatrix<Scalar1>::InnerIterator srcIt_t;
226 typedef Eigen::SparseMatrix<Scalar2> dest_t;
227 for (std::size_t k = 0; k != src.outerSize(); ++k)
229 for (srcIt_t it(src, (int)k); it; ++it)
231 dest.insert( it.row() + r, it.col() + c) = it.value();
236 Sp is an Eigen::SparseMatrix
238 template<typename Sp, typename M>
239 void cwiseInPlaceProduct(Sp& sp, M CONST& m)
241 // should be a transform_n() over makeNonZerosIterator(src)
242 for (std::size_t k = 0; k != sp.outerSize(); ++k)
244 for (typename Sp::InnerIterator it(sp, k); it; ++it)
246 it.valueRef() *= get<typename Eigen::internal::traits<Sp>::Scalar >(m, it.row(), it.col());
255 template<typename T, typename Arg>
256 T* create_new(Arg const& a)
262 Double* create_new(double const& d)
264 Double* res(new Double(1, 1, false));
270 Double* create_new(std::complex<double>const& c)
272 Double* res(new Double(1, 1, true));
273 res->set(0, 0, c.real());
274 res->setImg(0, 0, c.imag());
279 Double* create_new(Sparse const& s)
281 Sparse& cs(const_cast<Sparse&>(s)); // inherited member functions are not const-correct
282 Double* res(new Double(cs.getRows(), cs.getCols(), cs.isComplex()));
283 const_cast<Sparse&>(s).fill(*res);
294 Sparse::Sparse( Sparse const& src) : GenericType(src)
295 , matrixReal(src.matrixReal ? new RealSparse_t(*src.matrixReal) : 0)
296 , matrixCplx(src.matrixCplx ? new CplxSparse_t(*src.matrixCplx) : 0)
300 m_piDims[0] = const_cast<Sparse*>(&src)->getRows();
301 m_piDims[1] = const_cast<Sparse*>(&src)->getCols();
304 Sparse::Sparse(int _iRows, int _iCols, bool cplx)
305 : matrixReal(cplx ? 0 : new RealSparse_t(_iRows, _iCols))
306 , matrixCplx(cplx ? new CplxSparse_t(_iRows, _iCols) : 0)
310 m_iSize = _iRows * _iCols;
312 m_piDims[0] = _iRows;
313 m_piDims[1] = _iCols;
316 Sparse::Sparse(Double CONST& src)
318 create(src.getRows(), src.getCols(), src, RowWiseFullIterator(src.getRows(), src.getCols()), src.getSize());
321 Sparse::Sparse(Double CONST& src, Double CONST& idx)
323 double CONST* const endOfRow(idx.getReal() + idx.getRows());
324 create( static_cast<int>(*std::max_element(idx.getReal(), endOfRow))
325 , static_cast<int>(*std::max_element(endOfRow, endOfRow + idx.getRows()))
326 , src, makeIteratorFromVar(idx), idx.getSize() / 2 );
329 Sparse::Sparse(Double CONST& src, Double CONST& idx, Double CONST& dims)
331 create(static_cast<int>(dims.getReal(0, 0))
332 , static_cast<int>(dims.getReal(0, 1))
333 , src, makeIteratorFromVar(idx), idx.getSize() / 2);
336 Sparse::Sparse(RealSparse_t* realSp, CplxSparse_t* cplxSp): matrixReal(realSp), matrixCplx(cplxSp)
340 m_iCols = realSp->cols();
341 m_iRows = realSp->rows();
345 m_iCols = cplxSp->cols();
346 m_iRows = cplxSp->rows();
348 m_iSize = m_iCols * m_iRows;
350 m_piDims[0] = m_iRows;
351 m_piDims[1] = m_iCols;
354 Sparse::Sparse(Double CONST& xadj, Double CONST& adjncy, Double CONST& src, std::size_t r, std::size_t c)
356 Adjacency a(xadj.getReal(), adjncy.getReal());
357 create(static_cast<int>(r), static_cast<int>(c), src, makeIteratorFromVar(a), src.getSize());
360 template<typename DestIter>
361 void Sparse::create(int rows, int cols, Double CONST& src, DestIter o, std::size_t n)
365 m_iSize = cols * rows;
367 m_piDims[0] = m_iRows;
368 m_piDims[1] = m_iCols;
373 matrixCplx = new CplxSparse_t( rows, cols);
374 matrixCplx->reserve((int)n);
375 mycopy_n(makeMatrixIterator<std::complex<double> >(src, RowWiseFullIterator(src.getRows(), src.getCols())), n, makeMatrixIterator<std::complex<double> >(*matrixCplx, o));
379 matrixReal = new RealSparse_t(rows, cols);
380 matrixReal->reserve((int)n);
382 mycopy_n(makeMatrixIterator<double >(src, RowWiseFullIterator(src.getRows(), src.getCols())), n
383 , makeMatrixIterator<double>(*matrixReal, o));
388 void Sparse::fill(Double& dest, int r, int c) CONST
390 Sparse & cthis(const_cast<Sparse&>(*this));
393 mycopy_n(makeMatrixIterator<std::complex<double> >(*matrixCplx, RowWiseFullIterator(cthis.getRows(), cthis.getCols())), cthis.getSize()
394 , makeMatrixIterator<std::complex<double> >(dest, RowWiseFullIterator(dest.getRows(), dest.getCols(), r, c)));
398 mycopy_n( makeMatrixIterator<double>(*matrixReal, RowWiseFullIterator(cthis.getRows(), cthis.getCols())), cthis.getSize()
399 , makeMatrixIterator<double >(dest, RowWiseFullIterator(dest.getRows(), dest.getCols(), r, c)));
403 bool Sparse::set(int _iRows, int _iCols, std::complex<double> v, bool _bFinalize)
405 if (_iRows >= getRows() || _iCols >= getCols())
412 matrixReal->coeffRef(_iRows, _iCols) = v.real();
416 matrixCplx->coeffRef(_iRows, _iCols) = v;
426 bool Sparse::set(int _iRows, int _iCols, double _dblReal, bool _bFinalize)
428 if (_iRows >= getRows() || _iCols >= getCols())
435 matrixReal->coeffRef(_iRows, _iCols) = _dblReal;
439 matrixCplx->coeffRef(_iRows, _iCols) = std::complex<double>(_dblReal, 0);
450 void Sparse::finalize()
454 matrixCplx->prune(&keepForSparse<std::complex<double> >);
455 matrixCplx->finalize();
459 matrixReal->prune(&keepForSparse<double>);
460 matrixReal->finalize();
465 bool Sparse::isComplex() const
467 return static_cast<bool>(matrixCplx != NULL);
470 // TODO: should have both a bounds checking and a non-checking interface to elt access
471 double Sparse::get(int _iRows, int _iCols) const
473 return getReal(_iRows, _iCols);
476 double Sparse::getReal(int _iRows, int _iCols) const
481 res = matrixReal->coeff(_iRows, _iCols);
485 res = matrixCplx->coeff(_iRows, _iCols).real();
490 std::complex<double> Sparse::getImg(int _iRows, int _iCols) const
492 std::complex<double> res;
495 res = matrixCplx->coeff(_iRows, _iCols);
499 res = std::complex<double>(matrixReal->coeff(_iRows, _iCols), 0.);
505 void Sparse::whoAmI() CONST
507 std::cout << "types::Sparse";
510 Sparse* Sparse::clone(void) const
512 return new Sparse(*this);
515 GenericType::RealType Sparse::getType(void) CONST
520 bool Sparse::zero_set()
525 matrixReal->setZero();
529 matrixCplx->setZero();
535 // TODO: handle precision and line length
536 bool Sparse::toString(std::wostringstream& ostr) const
538 int iPrecision = getFormatSize();
542 res = ::toString(*matrixReal, iPrecision);
546 res = ::toString(*matrixCplx, iPrecision);
553 bool Sparse::resize(int _iNewRows, int _iNewCols)
555 if (_iNewRows <= getRows() && _iNewCols <= getCols())
557 //nothing to do: hence we do NOT fail
567 size_t iNonZeros = nonZeros();
568 RealSparse_t *newReal = new RealSparse_t(_iNewRows, _iNewCols);
569 newReal->reserve((int)iNonZeros);
573 int* pRows = new int[iNonZeros * 2];
575 int* pCols = pRows + iNonZeros;
578 double* pNonZeroR = new double[iNonZeros];
579 double* pNonZeroI = new double[iNonZeros];
580 outputValues(pNonZeroR, pNonZeroI);
582 typedef Eigen::Triplet<double> triplet;
583 std::vector<triplet> tripletList;
585 for (size_t i = 0 ; i < iNonZeros ; i++)
587 tripletList.push_back(triplet((int)pRows[i] - 1, (int)pCols[i] - 1, pNonZeroR[i]));
590 newReal->setFromTriplets(tripletList.begin(), tripletList.end());
593 matrixReal = newReal;
601 size_t iNonZeros = nonZeros();
602 CplxSparse_t *newCplx = new CplxSparse_t(_iNewRows, _iNewCols);
603 newCplx->reserve((int)iNonZeros);
606 int* pRows = new int[iNonZeros * 2];
608 int* pCols = pRows + iNonZeros;
611 double* pNonZeroR = new double[iNonZeros];
612 double* pNonZeroI = new double[iNonZeros];
613 outputValues(pNonZeroR, pNonZeroI);
615 typedef Eigen::Triplet<std::complex<double> > triplet;
616 std::vector<triplet> tripletList;
618 for (size_t i = 0 ; i < iNonZeros ; i++)
620 tripletList.push_back(triplet((int)pRows[i] - 1, (int)pCols[i] - 1, std::complex<double>(pNonZeroR[i], pNonZeroI[i])));
623 newCplx->setFromTriplets(tripletList.begin(), tripletList.end());
627 matrixCplx = newCplx;
635 m_iSize = _iNewRows * _iNewCols;
636 m_piDims[0] = m_iRows;
637 m_piDims[1] = m_iCols;
647 // TODO decide if a complex matrix with 0 imag can be == to a real matrix
648 // not true for dense (cf double.cpp)
649 bool Sparse::operator==(const InternalType& it) CONST
651 Sparse* otherSparse = const_cast<Sparse*>(dynamic_cast<Sparse const*>(&it));/* types::GenericType is not const-correct :( */
652 Sparse & cthis (const_cast<Sparse&>(*this));
654 if (otherSparse == NULL)
659 if (otherSparse->getRows() != cthis.getRows())
664 if (otherSparse->getCols() != cthis.getCols())
669 if (otherSparse->isComplex() != isComplex())
676 return equal(*matrixCplx, *otherSparse->matrixCplx);
680 return equal(*matrixReal, *otherSparse->matrixReal);
684 bool Sparse::one_set()
688 return setNonZero(*matrixCplx);
692 return setNonZero(*matrixReal);
696 void Sparse::toComplex()
702 matrixCplx = new CplxSparse_t(matrixReal->cast<std::complex<double> >());
715 InternalType* Sparse::insertNew(typed_list* _pArgs, InternalType* _pSource)
718 InternalType *pOut = NULL;
719 Sparse* pSource = _pSource->getAs<Sparse>();
721 int iDims = (int)_pArgs->size();
722 int* piMaxDim = new int[iDims];
723 int* piCountDim = new int[iDims];
724 bool bComplex = pSource->isComplex();
725 bool bUndefine = false;
727 //evaluate each argument and replace by appropriate value and compute the count of combinations
728 int iSeqCount = checkIndexesArguments(NULL, _pArgs, &pArg, piMaxDim, piCountDim);
731 return createEmptyDouble();
736 iSeqCount = -iSeqCount;
742 //manage : and $ in creation by insertion
744 int *piSourceDims = pSource->getDimsArray();
746 for (int i = 0 ; i < iDims ; i++)
751 if (pSource->isScalar())
758 piMaxDim[i] = piSourceDims[iSource];
759 piCountDim[i] = piSourceDims[iSource];
762 //replace pArg value by the new one
763 pArg[i] = createDoubleVector(piMaxDim[i]);
767 // piMaxDim[i] = piCountDim[i];
772 //remove last dimension at size 1
773 //remove last dimension if are == 1
774 for (int i = (iDims - 1) ; i >= 2 ; i--)
776 if (piMaxDim[i] == 1)
787 if (checkArgValidity(pArg) == false)
789 //contain bad index, like <= 0, ...
795 if (pSource->getCols() == 1)
797 pOut = new Sparse(piCountDim[0], 1, bComplex);
802 pOut = new Sparse(1, piCountDim[0], bComplex);
807 pOut = new Sparse(piMaxDim[0], piMaxDim[1], bComplex);
808 //pOut = pSource->createEmpty(iDims, piMaxDim, bComplex);
811 //fill with null item
812 Sparse* pSpOut = pOut->getAs<Sparse>();
814 //insert values in new matrix
815 InternalType* pOut2 = pSpOut->insert(&pArg, pSource);
824 Sparse* Sparse::insert(typed_list* _pArgs, InternalType* _pSource)
826 bool bNeedToResize = false;
827 int iDims = (int)_pArgs->size();
830 //sparse are only in 2 dims
842 Double* pSource = _pSource->getAs<Double>();
844 //evaluate each argument and replace by appropriate value and compute the count of combinations
845 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
854 if (getRows() == 1 || getCols() == 1)
857 if (getSize() < piMaxDim[0])
859 bNeedToResize = true;
861 //need to enlarge sparse dimensions
862 if (getCols() == 1 || getSize() == 0)
865 iNewRows = piMaxDim[0];
868 else if (getRows() == 1)
872 iNewCols = piMaxDim[0];
876 else if (getSize() < piMaxDim[0])
884 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
886 bNeedToResize = true;
887 iNewRows = Max(getRows(), piMaxDim[0]);
888 iNewCols = Max(getCols(), piMaxDim[1]);
892 //check number of insertion
893 if (pSource->isScalar() == false && pSource->getSize() != iSeqCount)
898 //now you are sure to be able to insert values
901 if (resize(iNewRows, iNewCols) == false)
908 if (pSource->isComplex() && isComplex() == false)
916 double* pIdx = pArg[0]->getAs<Double>()->get();
917 for (int i = 0 ; i < iSeqCount ; i++)
919 int iRow = static_cast<int>(pIdx[i] - 1) % getRows();
920 int iCol = static_cast<int>(pIdx[i] - 1) / getRows();
921 if (pSource->isScalar())
923 if (pSource->isComplex())
925 set(iRow, iCol, std::complex<double>(pSource->get(0), pSource->getImg(0)), false);
929 set(iRow, iCol, pSource->get(0), false);
934 if (pSource->isComplex())
936 set(iRow, iCol, std::complex<double>(pSource->get(i), pSource->getImg(i)), false);
940 set(iRow, iCol, pSource->get(i), false);
947 double* pIdxRow = pArg[0]->getAs<Double>()->get();
948 int iRowSize = pArg[0]->getAs<Double>()->getSize();
949 double* pIdxCol = pArg[1]->getAs<Double>()->get();
950 int iColSize = pArg[1]->getAs<Double>()->getSize();
952 for (int i = 0 ; i < iSeqCount ; i++)
954 if (pSource->isScalar())
956 if (pSource->isComplex())
958 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, std::complex<double>(pSource->get(0), pSource->getImg(0)), false);
962 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, pSource->get(0), false);
967 int iRowOrig = i % pSource->getRows();
968 int iColOrig = i / pSource->getRows();
970 if (pSource->isComplex())
972 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, std::complex<double>(pSource->get(iRowOrig, iColOrig), pSource->getImg(iRowOrig, iColOrig)), false);
976 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, pSource->get(iRowOrig, iColOrig), false);
986 Sparse* Sparse::insert(typed_list* _pArgs, Sparse* _pSource)
988 bool bNeedToResize = false;
989 int iDims = (int)_pArgs->size();
992 //sparse are only in 2 dims
1005 //evaluate each argument and replace by appropriate value and compute the count of combinations
1006 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1015 if (getRows() == 1 || getCols() == 1)
1018 bNeedToResize = true;
1019 if (getSize() < piMaxDim[0])
1021 //need to enlarge sparse dimensions
1022 if (getCols() == 1 || getSize() == 0)
1025 iNewRows = piMaxDim[0];
1028 else if (getRows() == 1)
1032 iNewCols = piMaxDim[0];
1036 else if (getSize() < piMaxDim[0])
1044 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
1046 bNeedToResize = true;
1047 iNewRows = Max(getRows(), piMaxDim[0]);
1048 iNewCols = Max(getCols(), piMaxDim[1]);
1052 //check number of insertion
1053 if (_pSource->isScalar() == false && _pSource->getSize() != iSeqCount)
1058 //now you are sure to be able to insert values
1061 if (resize(iNewRows, iNewCols) == false)
1068 if (_pSource->isComplex() && isComplex() == false)
1075 double* pIdx = pArg[0]->getAs<Double>()->get();
1076 for (int i = 0 ; i < iSeqCount ; i++)
1078 int iRow = static_cast<int>(pIdx[i] - 1) % getRows();
1079 int iCol = static_cast<int>(pIdx[i] - 1) / getRows();
1081 if (_pSource->isScalar())
1083 if (_pSource->isComplex())
1085 set(iRow, iCol, _pSource->getImg(0, 0), false);
1089 set(iRow, iCol, _pSource->get(0, 0), false);
1094 int iRowOrig = i % _pSource->getRows();
1095 int iColOrig = i / _pSource->getRows();
1096 if (_pSource->isComplex())
1098 set(iRow, iCol, _pSource->getImg(iRowOrig, iColOrig), false);
1102 set(iRow, iCol, _pSource->get(iRowOrig, iColOrig), false);
1109 double* pIdxRow = pArg[0]->getAs<Double>()->get();
1110 int iRowSize = pArg[0]->getAs<Double>()->getSize();
1111 double* pIdxCol = pArg[1]->getAs<Double>()->get();
1112 int iColSize = pArg[1]->getAs<Double>()->getSize();
1114 for (int i = 0 ; i < iSeqCount ; i++)
1116 if (_pSource->isScalar())
1118 if (_pSource->isComplex())
1120 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->getImg(0, 0), false);
1124 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(0, 0), false);
1129 int iRowOrig = i % _pSource->getRows();
1130 int iColOrig = i / _pSource->getRows();
1131 if (_pSource->isComplex())
1133 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->getImg(iRowOrig, iColOrig), false);
1137 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(iRowOrig, iColOrig), false);
1147 Sparse* Sparse::remove(typed_list* _pArgs)
1149 Sparse* pOut = NULL;
1150 int iDims = (int)_pArgs->size();
1153 //sparse are only in 2 dims
1166 //evaluate each argument and replace by appropriate value and compute the count of combinations
1167 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1173 bool* pbFull = new bool[iDims];
1174 //coord must represent all values on a dimension
1175 for (int i = 0 ; i < iDims ; i++)
1178 int iDimToCheck = getVarMaxDim(i, iDims);
1179 int iIndexSize = pArg[i]->getAs<GenericType>()->getSize();
1181 //we can have index more than once
1182 if (iIndexSize >= iDimToCheck)
1184 //size is good, now check datas
1185 double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
1186 for (int j = 0 ; j < iDimToCheck ; j++)
1189 for (int k = 0 ; k < iIndexSize ; k++)
1191 if ((int)pIndexes[k] == j + 1)
1202 //only one dims can be not full/entire
1203 bool bNotEntire = false;
1205 bool bTooMuchNotEntire = false;
1206 for (int i = 0 ; i < iDims ; i++)
1208 if (pbFull[i] == false)
1210 if (bNotEntire == false)
1217 bTooMuchNotEntire = true;
1223 if (bTooMuchNotEntire == true)
1230 //find index to keep
1231 int iNotEntireSize = pArg[iNotEntire]->getAs<GenericType>()->getSize();
1232 double* piNotEntireIndex = getDoubleArrayFromDouble(pArg[iNotEntire]);
1233 int iKeepSize = getVarMaxDim(iNotEntire, iDims);
1234 bool* pbKeep = new bool[iKeepSize];
1236 //fill pbKeep with true value
1237 for (int i = 0 ; i < iKeepSize ; i++)
1242 for (int i = 0 ; i < iNotEntireSize ; i++)
1244 int idx = (int)piNotEntireIndex[i] - 1;
1246 //don't care of value out of bounds
1247 if (idx < iKeepSize)
1249 pbKeep[idx] = false;
1253 int iNewDimSize = 0;
1254 for (int i = 0 ; i < iKeepSize ; i++)
1256 if (pbKeep[i] == true)
1263 int* piNewDims = new int[iDims];
1264 for (int i = 0 ; i < iDims ; i++)
1266 if (i == iNotEntire)
1268 piNewDims[i] = iNewDimSize;
1272 piNewDims[i] = getVarMaxDim(i, iDims);
1276 //remove last dimension if are == 1
1277 int iOrigDims = iDims;
1278 for (int i = (iDims - 1) ; i >= 2 ; i--)
1280 if (piNewDims[i] == 1)
1292 if (iNewDimSize == 0)
1294 return new Sparse(0, 0);
1298 //two cases, depends of original matrix/vector
1299 if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
1301 //special case for row vector
1302 pOut = new Sparse(1, iNewDimSize, isComplex());
1303 //in this case we have to care of 2nd dimension
1308 pOut = new Sparse(iNewDimSize, 1, isComplex());
1314 pOut = new Sparse(piNewDims[0], piNewDims[0], isComplex());
1318 //find a way to copy existing data to new variable ...
1320 int* piIndexes = new int[iOrigDims];
1321 int* piViewDims = new int[iOrigDims];
1322 for (int i = 0 ; i < iOrigDims ; i++)
1324 piViewDims[i] = getVarMaxDim(i, iOrigDims);
1327 for (int i = 0 ; i < getSize() ; i++)
1329 bool bByPass = false;
1330 getIndexesWithDims(i, piIndexes, piViewDims, iOrigDims);
1332 //check if piIndexes use removed indexes
1333 for (int j = 0 ; j < iNotEntireSize ; j++)
1335 if ((piNotEntireIndex[j] - 1) == piIndexes[iNotEntire])
1337 //by pass this value
1343 if (bByPass == false)
1348 pOut->set(iNewPos, getImg(i));
1352 pOut->set(iNewPos, get(i));
1358 //free allocated data
1359 for (int i = 0 ; i < iDims ; i++)
1361 if (pArg[i] != (*_pArgs)[i])
1368 delete[] piViewDims;
1372 bool Sparse::append(int r, int c, types::Sparse CONST* src)
1374 // 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;
1375 if (src->isComplex())
1381 if (src->isComplex())
1383 doAppend(*(src->matrixCplx), r, c, *matrixCplx);
1387 doAppend(*(src->matrixReal), r, c, *matrixCplx);
1392 doAppend(*(src->matrixReal), r, c, *matrixReal);
1397 return true; // realloc is meaningless for sparse matrices
1401 * create a new Sparse of dims according to resSize and fill it from currentSparse (along coords)
1403 InternalType* Sparse::extract(typed_list* _pArgs)
1405 Sparse* pOut = NULL;
1406 int iDims = (int)_pArgs->size();
1409 int* piMaxDim = new int[iDims];
1410 int* piCountDim = new int[iDims];
1412 //evaluate each argument and replace by appropriate value and compute the count of combinations
1413 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1416 if (_pArgs->size() == 0)
1424 return Double::Empty();
1430 if (piMaxDim[0] <= getSize())
1435 if (getRows() == 1 && getCols() != 1 && (*_pArgs)[0]->isColon() == false)
1437 //special case for row vector
1439 iNewCols = piCountDim[0];
1443 iNewRows = piCountDim[0];
1447 pOut = new Sparse(iNewRows, iNewCols, isComplex());
1448 double* pIdx = pArg[0]->getAs<Double>()->get();
1449 for (int i = 0 ; i < iSeqCount ; i++)
1451 int iRowRead = static_cast<int>(pIdx[i] - 1) % getRows();
1452 int iColRead = static_cast<int>(pIdx[i] - 1) / getRows();
1454 int iRowWrite = static_cast<int>(i) % iNewRows;
1455 int iColWrite = static_cast<int>(i) / iNewRows;
1458 std::complex<double> dbl = getImg(iRowRead, iColRead);
1459 if (dbl.real() != 0 || dbl.imag() != 0)
1461 //only non zero values
1462 pOut->set(iRowWrite, iColWrite, dbl, false);
1467 double dbl = get(iRowRead, iColRead);
1470 //only non zero values
1471 pOut->set(iRowWrite, iColWrite, dbl, false);
1483 if (piMaxDim[0] <= getRows() && piMaxDim[1] <= getCols())
1485 double* pIdxRow = pArg[0]->getAs<Double>()->get();
1486 double* pIdxCol = pArg[1]->getAs<Double>()->get();
1488 int iNewRows = pArg[0]->getAs<Double>()->getSize();
1489 int iNewCols = pArg[1]->getAs<Double>()->getSize();
1491 pOut = new Sparse(iNewRows, iNewCols, isComplex());
1494 for (int iRow = 0 ; iRow < iNewRows ; iRow++)
1496 for (int iCol = 0 ; iCol < iNewCols ; iCol++)
1500 std::complex<double> dbl = getImg((int)pIdxRow[iRow] - 1, (int)pIdxCol[iCol] - 1);
1501 if (dbl.real() != 0 || dbl.imag() != 0)
1503 //only non zero values
1504 pOut->set(iRow, iCol, dbl, false);
1509 double dbl = get((int)pIdxRow[iRow] - 1, (int)pIdxCol[iCol] - 1);
1512 //only non zero values
1513 pOut->set(iRow, iCol, dbl, false);
1530 Sparse* Sparse::extract(int nbCoords, int CONST* coords, int CONST* maxCoords, int CONST* resSize, bool asVector) CONST
1532 if ( (asVector && maxCoords[0] > getSize()) ||
1533 (asVector == false && maxCoords[0] > getRows()) ||
1534 (asVector == false && maxCoords[1] > getCols()))
1539 bool const cplx(isComplex());
1543 pSp = (getRows() == 1) ? new Sparse(1, resSize[0], cplx) : new Sparse(resSize[0], 1, cplx);
1547 pSp = new Sparse(resSize[0], resSize[1], cplx);
1549 // std::cerr<<"extracted sparse:"<<pSp->getRows()<<", "<<pSp->getCols()<<"seqCount="<<nbCoords<<"maxDim="<<maxCoords[0] <<","<< maxCoords[1]<<std::endl;
1551 ? copyToSparse(*this, Coords<true>(coords, getRows()), nbCoords
1552 , *pSp, RowWiseFullIterator(pSp->getRows(), pSp->getCols()))
1553 : copyToSparse(*this, Coords<false>(coords), nbCoords
1554 , *pSp, RowWiseFullIterator(pSp->getRows(), pSp->getCols()))))
1562 coords are Scilab 1-based
1563 extract std::make_pair(coords, asVector), rowIter
1565 template<typename Src, typename SrcTraversal, typename Sz, typename DestTraversal>
1566 bool Sparse::copyToSparse(Src CONST& src, SrcTraversal srcTrav, Sz n, Sparse& sp, DestTraversal destTrav)
1568 if (!(src.isComplex() || sp.isComplex()))
1570 mycopy_n(makeMatrixIterator<double>(src, srcTrav), n
1571 , makeMatrixIterator<double>(*sp.matrixReal, destTrav));
1576 mycopy_n(makeMatrixIterator<std::complex<double> >(src, srcTrav), n
1577 , makeMatrixIterator<std::complex<double> >(*sp.matrixCplx, destTrav));
1584 // GenericType because we might return a Double* for scalar operand
1585 Sparse* Sparse::add(Sparse const& o) const
1587 RealSparse_t* realSp(0);
1588 CplxSparse_t* cplxSp(0);
1589 if (isComplex() == false && o.isComplex() == false)
1592 realSp = new RealSparse_t(*matrixReal + * (o.matrixReal));
1594 else if (isComplex() == false && o.isComplex() == true)
1596 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >() + * (o.matrixCplx));
1598 else if (isComplex() == true && o.isComplex() == false)
1600 cplxSp = new CplxSparse_t(*matrixCplx + o.matrixReal->cast<std::complex<double> >());
1602 else if (isComplex() == true && o.isComplex() == true)
1604 cplxSp = new CplxSparse_t(*matrixCplx + * (o.matrixCplx));
1607 return new Sparse(realSp, cplxSp);
1610 // GenericType because we might return a Double* for scalar operand
1611 GenericType* Sparse::substract(Sparse const& o) const
1613 RealSparse_t* realSp(0);
1614 CplxSparse_t* cplxSp(0);
1615 if (isComplex() == false && o.isComplex() == false)
1618 realSp = new RealSparse_t(*matrixReal - * (o.matrixReal));
1620 else if (isComplex() == false && o.isComplex() == true)
1623 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >() - * (o.matrixCplx));
1625 else if (isComplex() == true && o.isComplex() == false)
1628 cplxSp = new CplxSparse_t(*matrixCplx - o.matrixReal->cast<std::complex<double> >());
1630 else if (isComplex() == true && o.isComplex() == true)
1633 cplxSp = new CplxSparse_t(*matrixCplx - * (o.matrixCplx));
1636 return new Sparse(realSp, cplxSp);
1639 Sparse* Sparse::multiply(double s) const
1641 return new Sparse( isComplex() ? 0 : new RealSparse_t((*matrixReal)*s)
1642 , isComplex() ? new CplxSparse_t((*matrixCplx)*s) : 0);
1645 Sparse* Sparse::multiply(std::complex<double> s) const
1647 return new Sparse( 0
1648 , isComplex() ? new CplxSparse_t((*matrixCplx) * s) : new CplxSparse_t((*matrixReal) * s));
1651 Sparse* Sparse::multiply(Sparse const& o) const
1653 RealSparse_t* realSp(0);
1654 CplxSparse_t* cplxSp(0);
1656 if (isComplex() == false && o.isComplex() == false)
1658 realSp = new RealSparse_t(*matrixReal * *(o.matrixReal));
1660 else if (isComplex() == false && o.isComplex() == true)
1662 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >() * *(o.matrixCplx));
1664 else if (isComplex() == true && o.isComplex() == false)
1666 cplxSp = new CplxSparse_t(*matrixCplx * o.matrixReal->cast<std::complex<double> >());
1668 else if (isComplex() == true && o.isComplex() == true)
1670 cplxSp = new CplxSparse_t(*matrixCplx * *(o.matrixCplx));
1673 return new Sparse(realSp, cplxSp);
1676 Sparse* Sparse::dotMultiply(Sparse CONST& o) const
1678 RealSparse_t* realSp(0);
1679 CplxSparse_t* cplxSp(0);
1680 if (isComplex() == false && o.isComplex() == false)
1682 realSp = new RealSparse_t(matrixReal->cwiseProduct(*(o.matrixReal)));
1684 else if (isComplex() == false && o.isComplex() == true)
1686 cplxSp = new CplxSparse_t(matrixReal->cast<std::complex<double> >().cwiseProduct( *(o.matrixCplx)));
1688 else if (isComplex() == true && o.isComplex() == false)
1690 cplxSp = new CplxSparse_t(matrixCplx->cwiseProduct(o.matrixReal->cast<std::complex<double> >()));
1692 else if (isComplex() == true && o.isComplex() == true)
1694 cplxSp = new CplxSparse_t(matrixCplx->cwiseProduct(*(o.matrixCplx)));
1697 return new Sparse(realSp, cplxSp);
1700 Sparse* Sparse::newTransposed() const
1702 return new Sparse( matrixReal ? new RealSparse_t(matrixReal->adjoint()) : 0
1703 , matrixCplx ? new CplxSparse_t(matrixCplx->adjoint()) : 0);
1708 BoolCast(std::complex<double> const& c): b(c.real() || c.imag()) {}
1709 operator bool () const
1713 operator double() const
1719 Sparse* Sparse::newOnes() const
1721 // result is never cplx
1722 return new Sparse( matrixReal
1723 ? new RealSparse_t(matrixReal->cast<bool>().cast<double>())
1724 : new RealSparse_t(matrixCplx->cast<BoolCast>().cast<double>())
1730 RealCast(std::complex<double> const& c): b(c.real()) {}
1731 operator bool () const
1735 operator double() const
1741 Sparse* Sparse::newReal() const
1743 return new Sparse( matrixReal
1745 : new RealSparse_t(matrixCplx->cast<RealCast>())
1749 std::size_t Sparse::nonZeros() const
1753 return matrixCplx->nonZeros();
1757 return matrixReal->nonZeros();
1760 std::size_t Sparse::nonZeros(std::size_t r) const
1765 int* piIndex = matrixReal->outerIndexPtr();
1766 res = piIndex[r + 1] - piIndex[r];
1770 int* piIndex = matrixCplx->outerIndexPtr();
1771 res = piIndex[r + 1] - piIndex[r];
1777 int* Sparse::getNbItemByRow(int* _piNbItemByRows)
1779 int* piNbItemByRows = new int[getRows() + 1];
1782 mycopy_n(matrixCplx->outerIndexPtr(), getRows() + 1, piNbItemByRows);
1786 mycopy_n(matrixReal->outerIndexPtr(), getRows() + 1, piNbItemByRows);
1789 for (int i = 0 ; i < getRows() ; i++)
1791 _piNbItemByRows[i] = piNbItemByRows[i + 1] - piNbItemByRows[i];
1794 delete[] piNbItemByRows;
1795 return _piNbItemByRows;
1798 int* Sparse::getColPos(int* _piColPos)
1802 mycopy_n(matrixCplx->innerIndexPtr(), nonZeros(), _piColPos);
1806 mycopy_n(matrixReal->innerIndexPtr(), nonZeros(), _piColPos);
1809 std::transform(_piColPos, _piColPos + nonZeros(), _piColPos, std::bind2nd(std::plus<double>(), 1));
1816 template<typename S> struct GetReal: std::unary_function<typename S::InnerIterator, double>
1818 double operator()(typename S::InnerIterator it) const
1823 template<> struct GetReal< Eigen::SparseMatrix<std::complex<double > > >
1824 : std::unary_function<Eigen::SparseMatrix<std::complex<double > > ::InnerIterator, double>
1826 double operator()( Eigen::SparseMatrix<std::complex<double > > ::InnerIterator it) const
1828 return it.value().real();
1831 template<typename S> struct GetImag: std::unary_function<typename S::InnerIterator, double>
1833 double operator()(typename S::InnerIterator it) const
1835 return it.value().imag();
1838 template<typename S> struct GetRow: std::unary_function<typename S::InnerIterator, int>
1840 int operator()(typename S::InnerIterator it) const
1842 return it.row() + 1;
1845 template<typename S> struct GetCol: std::unary_function<typename S::InnerIterator, int>
1847 int operator()(typename S::InnerIterator it) const
1849 return it.col() + 1;
1853 template<typename S, typename Out, typename F> Out sparseTransform(S& s, Out o, F f)
1855 for (std::size_t k(0); k < s.outerSize(); ++k)
1857 for (typename S::InnerIterator it(s, (int)k); it; ++it, ++o)
1866 std::pair<double*, double*> Sparse::outputValues(double* outReal, double* outImag)const
1869 ? std::make_pair(sparseTransform(*matrixReal, outReal, GetReal<RealSparse_t>()), outImag)
1870 : std::make_pair(sparseTransform(*matrixCplx, outReal, GetReal<CplxSparse_t>())
1871 , sparseTransform(*matrixCplx, outImag, GetImag<CplxSparse_t>()));
1874 int* Sparse::outputRowCol(int* out)const
1877 ? sparseTransform(*matrixReal, sparseTransform(*matrixReal, out, GetRow<RealSparse_t>()), GetCol<RealSparse_t>())
1878 : sparseTransform(*matrixCplx, sparseTransform(*matrixCplx, out, GetRow<CplxSparse_t>()), GetCol<CplxSparse_t>());
1880 double* Sparse::outputCols(double* out) const
1884 mycopy_n(matrixCplx->innerIndexPtr(), nonZeros(), out);
1888 mycopy_n(matrixReal->innerIndexPtr(), nonZeros(), out);
1891 return std::transform(out, out, out, std::bind2nd(std::plus<double>(), 1));
1895 void Sparse::opposite(void)
1899 std::complex<double>* data = matrixCplx->valuePtr();
1900 std::transform(data, data + matrixCplx->nonZeros(), data, std::negate<std::complex<double> >());
1904 double* data = matrixReal->valuePtr();
1905 std::transform(data, data + matrixReal->nonZeros(), data, std::negate<double>());
1909 SparseBool* Sparse::newLessThan(Sparse const&o) const
1911 return cwiseOp<std::less>(*this, o);
1914 SparseBool* Sparse::newGreaterThan(Sparse const&o) const
1916 return cwiseOp<std::greater>(*this, o);
1919 SparseBool* Sparse::newNotEqualTo(Sparse const&o) const
1921 return cwiseOp<std::not_equal_to>(*this, o);
1924 SparseBool* Sparse::newLessOrEqual(Sparse const&o) const
1926 return cwiseOp<std::less_equal>(*this, o);
1929 SparseBool* Sparse::newGreaterOrEqual(Sparse const&o) const
1931 return cwiseOp<std::greater_equal>(*this, o);
1934 SparseBool* Sparse::newEqualTo(Sparse const&o) const
1936 return cwiseOp<std::equal_to>(*this, o);
1939 bool Sparse::reshape(int* _piDims, int _iDims)
1951 bOk = reshape(_piDims[0], iCols);
1957 bool Sparse::reshape(int _iNewRows, int _iNewCols)
1959 if (_iNewRows * _iNewCols != getRows() * getCols())
1970 size_t iNonZeros = nonZeros();
1971 RealSparse_t *newReal = new RealSparse_t(_iNewRows, _iNewCols);
1972 newReal->reserve((int)iNonZeros);
1975 int* pRows = new int[iNonZeros * 2];
1976 outputRowCol(pRows);
1977 int* pCols = pRows + iNonZeros;
1980 double* pNonZeroR = new double[iNonZeros];
1981 double* pNonZeroI = new double[iNonZeros];
1982 outputValues(pNonZeroR, pNonZeroI);
1984 typedef Eigen::Triplet<double> triplet;
1985 std::vector<triplet> tripletList;
1987 for (size_t i = 0 ; i < iNonZeros ; i++)
1989 int iCurrentPos = ((int)pCols[i] - 1) * getRows() + ((int)pRows[i] - 1);
1990 tripletList.push_back(triplet((int)(iCurrentPos % _iNewRows), (int)(iCurrentPos / _iNewRows), pNonZeroR[i]));
1993 newReal->setFromTriplets(tripletList.begin(), tripletList.end());
1996 matrixReal = newReal;
2004 size_t iNonZeros = nonZeros();
2005 CplxSparse_t *newCplx = new CplxSparse_t(_iNewRows, _iNewCols);
2006 newCplx->reserve((int)iNonZeros);
2009 int* pRows = new int[iNonZeros * 2];
2010 outputRowCol(pRows);
2011 int* pCols = pRows + iNonZeros;
2014 double* pNonZeroR = new double[iNonZeros];
2015 double* pNonZeroI = new double[iNonZeros];
2016 outputValues(pNonZeroR, pNonZeroI);
2018 typedef Eigen::Triplet<std::complex<double> > triplet;
2019 std::vector<triplet> tripletList;
2021 for (size_t i = 0 ; i < iNonZeros ; i++)
2023 int iCurrentPos = ((int)pCols[i] - 1) * getRows() + ((int)pRows[i] - 1);
2024 tripletList.push_back(triplet((int)(iCurrentPos % _iNewRows), (int)(iCurrentPos / _iNewRows), std::complex<double>(pNonZeroR[i], pNonZeroI[i])));
2027 newCplx->setFromTriplets(tripletList.begin(), tripletList.end());
2030 matrixCplx = newCplx;
2036 m_iRows = _iNewRows;
2037 m_iCols = _iNewCols;
2038 m_iSize = _iNewRows * _iNewCols;
2041 m_piDims[0] = m_iRows;
2042 m_piDims[1] = m_iCols;
2055 // SparseBool* SparseBool::new
2057 SparseBool::SparseBool(Bool CONST& src)
2059 create(src.getRows(), src.getCols(), src, RowWiseFullIterator(src.getRows(), src.getCols()), src.getSize());
2061 /* @param src : Bool matrix to copy into a new sparse matrix
2062 @param idx : Double matrix to use as indexes to get values from the src
2064 SparseBool::SparseBool(Bool CONST& src, Double CONST& idx)
2066 double CONST* const endOfRow(idx.getReal() + idx.getRows());
2067 create( static_cast<int>(*std::max_element(idx.getReal(), endOfRow))
2068 , static_cast<int>(*std::max_element(endOfRow, endOfRow + idx.getRows()))
2069 , src, makeIteratorFromVar(idx), idx.getSize() / 2 );
2072 /* @param src : Bool matrix to copy into a new sparse matrix
2073 @param idx : Double matrix to use as indexes to get values from the src
2074 @param dims : Double matrix containing the dimensions of the new matrix
2076 SparseBool::SparseBool(Bool CONST& src, Double CONST& idx, Double CONST& dims)
2078 create((int)dims.getReal(0, 0) , (int)dims.getReal(0, 1) , src, makeIteratorFromVar(idx), (int)idx.getSize() / 2);
2081 SparseBool::SparseBool(int _iRows, int _iCols) : matrixBool(new BoolSparse_t(_iRows, _iCols))
2085 m_iSize = _iRows * _iCols;
2087 m_piDims[0] = _iRows;
2088 m_piDims[1] = _iCols;
2091 SparseBool::SparseBool(SparseBool const& src) : GenericType(src), matrixBool(new BoolSparse_t(*src.matrixBool))
2094 m_iRows = const_cast<SparseBool*>(&src)->getRows();
2095 m_iCols = const_cast<SparseBool*>(&src)->getCols();
2096 m_iSize = m_iRows * m_iCols;
2097 m_piDims[0] = m_iRows;
2098 m_piDims[1] = m_iCols;
2101 SparseBool::SparseBool(BoolSparse_t* src) : matrixBool(src)
2103 m_iRows = src->rows();
2104 m_iCols = src->cols();
2105 m_iSize = m_iRows * m_iCols;
2107 m_piDims[0] = m_iRows;
2108 m_piDims[1] = m_iCols;
2111 template<typename DestIter>
2112 void SparseBool::create(int rows, int cols, Bool CONST& src, DestIter o, std::size_t n)
2116 m_iSize = cols * rows;
2118 m_piDims[0] = m_iRows;
2119 m_piDims[1] = m_iCols;
2121 matrixBool = new BoolSparse_t(rows, cols);
2123 matrixBool->reserve((int)n);
2124 mycopy_n(makeMatrixIterator<int>(src, RowWiseFullIterator(src.getRows(), src.getCols())), n
2125 , makeMatrixIterator<bool>(*matrixBool, o));
2130 bool SparseBool::toString(std::wostringstream& ostr) const
2132 ostr << ::toString(*matrixBool, 0);
2136 void SparseBool::whoAmI() CONST
2138 std::cout << "types::SparseBool";
2141 SparseBool* SparseBool::clone(void) const
2143 return new SparseBool(*this);
2146 bool SparseBool::resize(int _iNewRows, int _iNewCols)
2148 if (_iNewRows <= getRows() && _iNewCols <= getCols())
2150 //nothing to do: hence we do NOT fail
2158 size_t iNonZeros = nbTrue();
2160 BoolSparse_t *newBool = new BoolSparse_t(_iNewRows, _iNewCols);
2161 newBool->reserve((int)iNonZeros);
2164 int* pRows = new int[iNonZeros * 2];
2165 outputRowCol(pRows);
2166 int* pCols = pRows + iNonZeros;
2168 typedef Eigen::Triplet<bool> triplet;
2169 std::vector<triplet> tripletList;
2171 for (size_t i = 0 ; i < iNonZeros ; i++)
2173 tripletList.push_back(triplet((int)pRows[i] - 1, (int)pCols[i] - 1, true));
2176 newBool->setFromTriplets(tripletList.begin(), tripletList.end());
2179 matrixBool = newBool;
2182 m_iRows = _iNewRows;
2183 m_iCols = _iNewCols;
2184 m_iSize = _iNewRows * _iNewCols;
2185 m_piDims[0] = m_iRows;
2186 m_piDims[1] = m_iCols;
2198 SparseBool* SparseBool::insert(typed_list* _pArgs, SparseBool* _pSource)
2200 bool bNeedToResize = false;
2201 int iDims = (int)_pArgs->size();
2204 //sparse are only in 2 dims
2217 //evaluate each argument and replace by appropriate value and compute the count of combinations
2218 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
2227 if (getRows() == 1 || getCols() == 1)
2230 if (getSize() < piMaxDim[0])
2232 bNeedToResize = true;
2234 //need to enlarge sparse dimensions
2235 if (getCols() == 1 || getSize() == 0)
2238 iNewRows = piMaxDim[0];
2241 else if (getRows() == 1)
2245 iNewCols = piMaxDim[0];
2249 else if (getSize() < piMaxDim[0])
2257 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
2259 bNeedToResize = true;
2260 iNewRows = Max(getRows(), piMaxDim[0]);
2261 iNewCols = Max(getCols(), piMaxDim[1]);
2265 //check number of insertion
2266 if (_pSource->isScalar() == false && _pSource->getSize() != iSeqCount)
2271 //now you are sure to be able to insert values
2274 if (resize(iNewRows, iNewCols) == false)
2282 double* pIdx = pArg[0]->getAs<Double>()->get();
2283 for (int i = 0 ; i < iSeqCount ; i++)
2285 int iRow = static_cast<int>(pIdx[i] - 1) % getRows();
2286 int iCol = static_cast<int>(pIdx[i] - 1) / getRows();
2288 if (_pSource->isScalar())
2290 set(iRow, iCol, _pSource->get(0, 0), false);
2294 int iRowOrig = i % _pSource->getRows();
2295 int iColOrig = i / _pSource->getRows();
2296 set(iRow, iCol, _pSource->get(iRowOrig, iColOrig), false);
2302 double* pIdxRow = pArg[0]->getAs<Double>()->get();
2303 int iRowSize = pArg[0]->getAs<Double>()->getSize();
2304 double* pIdxCol = pArg[1]->getAs<Double>()->get();
2305 int iColSize = pArg[1]->getAs<Double>()->getSize();
2307 for (int i = 0 ; i < iSeqCount ; i++)
2309 if (_pSource->isScalar())
2311 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(0, 0), false);
2315 int iRowOrig = i % _pSource->getRows();
2316 int iColOrig = i / _pSource->getRows();
2317 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, _pSource->get(iRowOrig, iColOrig), false);
2326 SparseBool* SparseBool::insert(typed_list* _pArgs, InternalType* _pSource)
2328 bool bNeedToResize = false;
2329 int iDims = (int)_pArgs->size();
2332 //sparse are only in 2 dims
2344 Bool* pSource = _pSource->getAs<Bool>();
2346 //evaluate each argument and replace by appropriate value and compute the count of combinations
2347 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
2356 if (getRows() == 1 || getCols() == 1)
2359 bNeedToResize = true;
2360 if (getSize() < piMaxDim[0])
2362 //need to enlarge sparse dimensions
2363 if (getCols() == 1 || getSize() == 0)
2366 iNewRows = piMaxDim[0];
2369 else if (getRows() == 1)
2373 iNewCols = piMaxDim[0];
2377 else if (getSize() < piMaxDim[0])
2385 if (piMaxDim[0] > getRows() || piMaxDim[1] > getCols())
2387 bNeedToResize = true;
2388 iNewRows = Max(getRows(), piMaxDim[0]);
2389 iNewCols = Max(getCols(), piMaxDim[1]);
2393 //check number of insertion
2394 if (pSource->isScalar() == false && pSource->getSize() != iSeqCount)
2399 //now you are sure to be able to insert values
2402 if (resize(iNewRows, iNewCols) == false)
2410 double* pIdx = pArg[0]->getAs<Double>()->get();
2411 for (int i = 0 ; i < iSeqCount ; i++)
2413 int iRow = static_cast<int>(pIdx[i] - 1) % getRows();
2414 int iCol = static_cast<int>(pIdx[i] - 1) / getRows();
2415 if (pSource->isScalar())
2417 set(iRow, iCol, pSource->get(0) != 0, false);
2421 set(iRow, iCol, pSource->get(i) != 0, false);
2427 double* pIdxRow = pArg[0]->getAs<Double>()->get();
2428 int iRowSize = pArg[0]->getAs<Double>()->getSize();
2429 double* pIdxCol = pArg[1]->getAs<Double>()->get();
2430 int iColSize = pArg[1]->getAs<Double>()->getSize();
2432 for (int i = 0 ; i < iSeqCount ; i++)
2434 if (pSource->isScalar())
2436 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, pSource->get(0) != 0, false);
2440 int iRowOrig = i % pSource->getRows();
2441 int iColOrig = i / pSource->getRows();
2443 set((int)pIdxRow[i % iRowSize] - 1, (int)pIdxCol[i / iRowSize] - 1, pSource->get(iRowOrig, iColOrig) != 0, false);
2452 SparseBool* SparseBool::remove(typed_list* _pArgs)
2454 SparseBool* pOut = NULL;
2455 int iDims = (int)_pArgs->size();
2458 //sparse are only in 2 dims
2471 //evaluate each argument and replace by appropriate value and compute the count of combinations
2472 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
2478 bool* pbFull = new bool[iDims];
2479 //coord must represent all values on a dimension
2480 for (int i = 0 ; i < iDims ; i++)
2483 int iDimToCheck = getVarMaxDim(i, iDims);
2484 int iIndexSize = pArg[i]->getAs<GenericType>()->getSize();
2486 //we can have index more than once
2487 if (iIndexSize >= iDimToCheck)
2489 //size is good, now check datas
2490 double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
2491 for (int j = 0 ; j < iDimToCheck ; j++)
2494 for (int k = 0 ; k < iIndexSize ; k++)
2496 if ((int)pIndexes[k] == j + 1)
2507 //only one dims can be not full/entire
2508 bool bNotEntire = false;
2510 bool bTooMuchNotEntire = false;
2511 for (int i = 0 ; i < iDims ; i++)
2513 if (pbFull[i] == false)
2515 if (bNotEntire == false)
2522 bTooMuchNotEntire = true;
2528 if (bTooMuchNotEntire == true)
2535 //find index to keep
2536 int iNotEntireSize = pArg[iNotEntire]->getAs<GenericType>()->getSize();
2537 double* piNotEntireIndex = getDoubleArrayFromDouble(pArg[iNotEntire]);
2538 int iKeepSize = getVarMaxDim(iNotEntire, iDims);
2539 bool* pbKeep = new bool[iKeepSize];
2541 //fill pbKeep with true value
2542 for (int i = 0 ; i < iKeepSize ; i++)
2547 for (int i = 0 ; i < iNotEntireSize ; i++)
2549 int idx = (int)piNotEntireIndex[i] - 1;
2551 //don't care of value out of bounds
2552 if (idx < iKeepSize)
2554 pbKeep[idx] = false;
2558 int iNewDimSize = 0;
2559 for (int i = 0 ; i < iKeepSize ; i++)
2561 if (pbKeep[i] == true)
2568 int* piNewDims = new int[iDims];
2569 for (int i = 0 ; i < iDims ; i++)
2571 if (i == iNotEntire)
2573 piNewDims[i] = iNewDimSize;
2577 piNewDims[i] = getVarMaxDim(i, iDims);
2581 //remove last dimension if are == 1
2582 int iOrigDims = iDims;
2583 for (int i = (iDims - 1) ; i >= 2 ; i--)
2585 if (piNewDims[i] == 1)
2597 if (iNewDimSize == 0)
2599 return new SparseBool(0, 0);
2603 //two cases, depends of original matrix/vector
2604 if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
2606 //special case for row vector
2607 pOut = new SparseBool(1, iNewDimSize);
2608 //in this case we have to care of 2nd dimension
2613 pOut = new SparseBool(iNewDimSize, 1);
2619 pOut = new SparseBool(piNewDims[0], piNewDims[0]);
2623 //find a way to copy existing data to new variable ...
2625 int* piIndexes = new int[iOrigDims];
2626 int* piViewDims = new int[iOrigDims];
2627 for (int i = 0 ; i < iOrigDims ; i++)
2629 piViewDims[i] = getVarMaxDim(i, iOrigDims);
2632 for (int i = 0 ; i < getSize() ; i++)
2634 bool bByPass = false;
2635 getIndexesWithDims(i, piIndexes, piViewDims, iOrigDims);
2637 //check if piIndexes use removed indexes
2638 for (int j = 0 ; j < iNotEntireSize ; j++)
2640 if ((piNotEntireIndex[j] - 1) == piIndexes[iNotEntire])
2642 //by pass this value
2648 if (bByPass == false)
2651 pOut->set(iNewPos, get(i));
2656 //free allocated data
2657 for (int i = 0 ; i < iDims ; i++)
2659 if (pArg[i] != (*_pArgs)[i])
2666 delete[] piViewDims;
2670 bool SparseBool::append(int r, int c, SparseBool CONST* src)
2672 doAppend(*src, r, c, *matrixBool);
2677 InternalType* SparseBool::insertNew(typed_list* _pArgs, InternalType* _pSource)
2680 InternalType *pOut = NULL;
2681 SparseBool* pSource = _pSource->getAs<SparseBool>();
2683 int iDims = (int)_pArgs->size();
2684 int* piMaxDim = new int[iDims];
2685 int* piCountDim = new int[iDims];
2686 bool bUndefine = false;
2688 //evaluate each argument and replace by appropriate value and compute the count of combinations
2689 int iSeqCount = checkIndexesArguments(NULL, _pArgs, &pArg, piMaxDim, piCountDim);
2692 return createEmptyDouble();
2697 iSeqCount = -iSeqCount;
2703 //manage : and $ in creation by insertion
2705 int *piSourceDims = pSource->getDimsArray();
2707 for (int i = 0 ; i < iDims ; i++)
2709 if (pArg[i] == NULL)
2712 if (pSource->isScalar())
2719 piMaxDim[i] = piSourceDims[iSource];
2720 piCountDim[i] = piSourceDims[iSource];
2723 //replace pArg value by the new one
2724 pArg[i] = createDoubleVector(piMaxDim[i]);
2728 // piMaxDim[i] = piCountDim[i];
2733 //remove last dimension at size 1
2734 //remove last dimension if are == 1
2735 for (int i = (iDims - 1) ; i >= 2 ; i--)
2737 if (piMaxDim[i] == 1)
2748 if (checkArgValidity(pArg) == false)
2750 //contain bad index, like <= 0, ...
2756 if (pSource->getCols() == 1)
2758 pOut = new SparseBool(piCountDim[0], 1);
2763 pOut = new SparseBool(1, piCountDim[0]);
2768 pOut = new SparseBool(piMaxDim[0], piMaxDim[1]);
2771 //fill with null item
2772 SparseBool* pSpOut = pOut->getAs<SparseBool>();
2774 //insert values in new matrix
2775 InternalType* pOut2 = pSpOut->insert(&pArg, pSource);
2784 SparseBool* SparseBool::extract(int nbCoords, int CONST* coords, int CONST* maxCoords, int CONST* resSize, bool asVector) CONST
2786 if ( (asVector && maxCoords[0] > getSize()) ||
2787 (asVector == false && maxCoords[0] > getRows()) ||
2788 (asVector == false && maxCoords[1] > getCols()))
2793 SparseBool * pSp (0);
2796 pSp = (getRows() == 1) ? new SparseBool(1, resSize[0]) : new SparseBool(resSize[0], 1);
2797 mycopy_n(makeMatrixIterator<bool>(*this, Coords<true>(coords, getRows())), nbCoords
2798 , makeMatrixIterator<bool>(*(pSp->matrixBool), RowWiseFullIterator(pSp->getRows(), pSp->getCols())));
2802 pSp = new SparseBool(resSize[0], resSize[1]);
2803 mycopy_n(makeMatrixIterator<bool>(*this, Coords<false>(coords, getRows())), nbCoords
2804 , makeMatrixIterator<bool>(*(pSp->matrixBool), RowWiseFullIterator(pSp->getRows(), pSp->getCols())));
2811 * create a new SparseBool of dims according to resSize and fill it from currentSparseBool (along coords)
2813 InternalType* SparseBool::extract(typed_list* _pArgs)
2815 SparseBool* pOut = NULL;
2816 int iDims = (int)_pArgs->size();
2819 int* piMaxDim = new int[iDims];
2820 int* piCountDim = new int[iDims];
2822 //evaluate each argument and replace by appropriate value and compute the count of combinations
2823 int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
2826 if (_pArgs->size() == 0)
2834 return Double::Empty();
2840 // Check that we stay inside the input size.
2841 if (piMaxDim[0] <= getSize())
2846 if (getRows() == 1 && getCols() != 1 && (*_pArgs)[0]->isColon() == false)
2848 //special case for row vector
2850 iNewCols = piCountDim[0];
2854 iNewRows = piCountDim[0];
2858 pOut = new SparseBool(iNewRows, iNewCols);
2859 double* pIdx = pArg[0]->getAs<Double>()->get();
2860 // Write in output all elements extract from input.
2861 for (int i = 0 ; i < iSeqCount ; i++)
2863 int iRowRead = static_cast<int>(pIdx[i] - 1) % getRows();
2864 int iColRead = static_cast<int>(pIdx[i] - 1) / getRows();
2866 int iRowWrite = static_cast<int>(i) % iNewRows;
2867 int iColWrite = static_cast<int>(i) / iNewRows;
2869 bool bValue = get(iRowRead, iColRead);
2872 //only non zero values
2873 pOut->set(iRowWrite, iColWrite, true, false);
2884 // Check that we stay inside the input size.
2885 if (piMaxDim[0] <= getRows() && piMaxDim[1] <= getCols())
2887 double* pIdxRow = pArg[0]->getAs<Double>()->get();
2888 double* pIdxCol = pArg[1]->getAs<Double>()->get();
2890 int iNewRows = pArg[0]->getAs<Double>()->getSize();
2891 int iNewCols = pArg[1]->getAs<Double>()->getSize();
2893 pOut = new SparseBool(iNewRows, iNewCols);
2896 // Write in output all elements extract from input.
2897 for (int iRow = 0 ; iRow < iNewRows ; iRow++)
2899 for (int iCol = 0 ; iCol < iNewCols ; iCol++)
2901 bool bValue = get((int)pIdxRow[iRow] - 1, (int)pIdxCol[iCol] - 1);
2904 //only non zero values
2905 pOut->set(iRow, iCol, true, false);
2921 SparseBool* SparseBool::newTransposed() const
2923 return new SparseBool(new BoolSparse_t(matrixBool->adjoint()));
2926 std::size_t SparseBool::nbTrue() const
2928 return matrixBool->nonZeros() ;
2930 std::size_t SparseBool::nbTrue(std::size_t r) const
2932 int* piIndex = matrixBool->outerIndexPtr();
2933 return piIndex[r + 1] - piIndex[r];
2936 int* SparseBool::getNbItemByRow(int* _piNbItemByRows)
2938 int* piNbItemByRows = new int[getRows() + 1];
2939 mycopy_n(matrixBool->outerIndexPtr(), getRows() + 1, piNbItemByRows);
2941 for (int i = 0 ; i < getRows() ; i++)
2943 _piNbItemByRows[i] = piNbItemByRows[i + 1] - piNbItemByRows[i];
2946 delete[] piNbItemByRows;
2947 return _piNbItemByRows;
2950 int* SparseBool::getColPos(int* _piColPos)
2952 mycopy_n(matrixBool->innerIndexPtr(), getRows(), _piColPos);
2956 int* SparseBool::outputRowCol(int* out)const
2958 return sparseTransform(*matrixBool, sparseTransform(*matrixBool, out, GetRow<BoolSparse_t>()), GetCol<BoolSparse_t>());
2961 bool SparseBool::operator==(const InternalType& it) CONST
2963 SparseBool* otherSparse = const_cast<SparseBool*>(dynamic_cast<SparseBool const*>(&it));/* types::GenericType is not const-correct :( */
2965 && (otherSparse->getRows() != getRows())
2966 && (otherSparse->getCols() != getCols())
2967 && equal(*matrixBool, *otherSparse->matrixBool));
2970 bool SparseBool::operator!=(const InternalType& it) CONST
2972 return !(*this == it);
2975 void SparseBool::finalize()
2977 matrixBool->prune(&keepForSparse<bool>);
2978 matrixBool->finalize();
2981 GenericType::RealType SparseBool::getType(void) CONST
2983 return InternalType::RealSparseBool;
2986 bool SparseBool::get(int r, int c) CONST
2988 return matrixBool->coeff(r, c);
2991 bool SparseBool::set(int _iRows, int _iCols, bool _bVal, bool _bFinalize) CONST
2993 matrixBool->coeffRef(_iRows, _iCols) = _bVal;
3002 void SparseBool::fill(Bool& dest, int r, int c) CONST
3004 mycopy_n(makeMatrixIterator<bool >(*matrixBool, RowWiseFullIterator(getRows(), getCols())), getSize()
3005 , makeMatrixIterator<bool >(dest, RowWiseFullIterator(dest.getRows(), dest.getCols(), r, c)));
3008 Sparse* SparseBool::newOnes() const
3010 return new Sparse(new types::Sparse::RealSparse_t(matrixBool->cast<double>()), 0);
3013 SparseBool* SparseBool::newNotEqualTo(SparseBool const&o) const
3015 return cwiseOp<std::not_equal_to>(*this, o);
3018 SparseBool* SparseBool::newEqualTo(SparseBool const&o) const
3020 return cwiseOp<std::equal_to>(*this, o);
3023 SparseBool* SparseBool::newLogicalOr(SparseBool const&o) const
3025 return cwiseOp<std::logical_or>(*this, o);
3028 SparseBool* SparseBool::newLogicalAnd(SparseBool const&o) const
3030 return cwiseOp<std::logical_and>(*this, o);
3033 bool SparseBool::reshape(int* _piDims, int _iDims)
3045 bOk = reshape(_piDims[0], iCols);
3051 bool SparseBool::reshape(int _iNewRows, int _iNewCols)
3053 if (_iNewRows * _iNewCols != getRows() * getCols())
3062 size_t iNonZeros = matrixBool->nonZeros();
3063 BoolSparse_t *newBool = new BoolSparse_t(_iNewRows, _iNewCols);
3064 newBool->reserve((int)iNonZeros);
3067 int* pRows = new int[iNonZeros * 2];
3068 outputRowCol(pRows);
3069 int* pCols = pRows + iNonZeros;
3071 typedef Eigen::Triplet<bool> triplet;
3072 std::vector<triplet> tripletList;
3074 for (size_t i = 0 ; i < iNonZeros ; i++)
3076 int iCurrentPos = ((int)pCols[i] - 1) * getRows() + ((int)pRows[i] - 1);
3077 tripletList.push_back(triplet((int)(iCurrentPos % _iNewRows), (int)(iCurrentPos / _iNewRows), true));
3080 newBool->setFromTriplets(tripletList.begin(), tripletList.end());
3083 matrixBool = newBool;
3086 m_iRows = _iNewRows;
3087 m_iCols = _iNewCols;
3088 m_iSize = _iNewRows * _iNewCols;
3091 m_piDims[0] = m_iRows;
3092 m_piDims[1] = m_iCols;