2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2008-2008 - 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
12 #ifndef MATRIXITERATORS_HXX
13 #define MATRIXITERATORS_HXX
24 In order to reuse code for the various Matrix Classes, we need some uniform API to access elements.
25 We cannot use runtime polymorphism (with dynamic dispatching) because of the runtime cost so we have to
26 use compile-time polymorphism with templates.
28 The provided free function templates get<>() and set<>() provide such an uniform API.
30 In order to perform element-wise operations on Matrices (copy, partial or total assignments, etc.),
31 we provide an iterator. To enable reading (with get<>()) or writiting (with set<>()) we provide an Accessor<> proxy.
33 As is it common to iterate over a sub-matrix according to indices given by a Scilab variable (Double) we provide
34 an iterator created from such a variable (IteratorFromVar).
37 struct UndefinedAccessorForType {};
40 This free function overloads perform read access into a 2D container, using 0-based indices.
41 @param s the 2D structure used to fetch a value of type V.
42 @param r : the row (0 based)
43 @param c : the column (0 based)
44 @return : the value of type V at row r and column c of structure s
47 template<typename V, typename S> V get(S SPARSE_CONST&, int, int)
49 return UndefinedAccessorForType<S>();
52 template<> double get(types::Double SPARSE_CONST& d, int r, int c)
54 return d.getReal(r, c);
56 template<> std::complex<double> get(types::Double SPARSE_CONST& d, int r, int c)
58 return std::complex<double>(d.getReal(r, c), d.getImg(r, c));
61 template<> bool get(types::Bool SPARSE_CONST& d, int r, int c)
63 return d.get(r, c) == 1;
65 template<> int get(types::Bool SPARSE_CONST& d, int r, int c)
69 template<> bool get(types::SparseBool SPARSE_CONST& d, int r, int c)
73 template<> int get(types::SparseBool SPARSE_CONST& d, int r, int c)
78 template<> double get(types::Sparse SPARSE_CONST& s, int r, int c)
80 return s.getReal(r, c);
82 template<> std::complex<double> get(types::Sparse SPARSE_CONST& s, int r, int c)
87 template<> double get(types::Sparse::RealSparse_t SPARSE_CONST&s, int r, int c)
91 template<> std::complex<double> get(types::Sparse::RealSparse_t SPARSE_CONST&s, int r, int c)
93 return std::complex<double>(s.coeff(r, c), 0.);
96 template<> bool get(types::SparseBool::BoolSparse_t SPARSE_CONST& d, int r, int c)
101 template<> double get(types::Sparse::CplxSparse_t SPARSE_CONST&s, int r, int c)
103 return s.coeff(r, c).real();
105 template<> std::complex<double> get(types::Sparse::CplxSparse_t SPARSE_CONST&s, int r, int c)
107 return s.coeff(r, c);
112 This free function overloads perform write access into a 2D container, using 0-based indices.
113 @param s the 2D structure used to fetch a value of type V.
114 @param r : the row (0 based)
115 @param c : the column (0 based)
116 @param v : the value of type V to set at row r and column c of structure s
117 @return : true iff everything went ok (should throw otherwise anyway).
121 template<typename S, typename V> bool set(S &, int, int, V)
123 return UndefinedAccessorForType<S>();
126 template<> bool set(types::Double & d, int r, int c, double v)
128 return d.set(r, c, v);
130 template<> bool set(types::Double & d, int r, int c, std::complex<double> v)
132 return d.set(r, c, v.real()) && d.setImg(r, c, v.imag());
135 template<> bool set(types::Sparse & s, int r, int c, double v)
137 return s.set(r, c, v);
139 template<> bool set(types::Sparse & s, int r, int c, std::complex<double> v)
141 return s.set(r, c, v);
143 template<> bool set(types::Bool & d, int r, int c, bool v)
145 return d.set(r, c, v);
147 template<> bool set(types::SparseBool & d, int r, int c, bool v)
149 return d.set(r, c, v);
151 template<> bool set(types::Bool & d, int r, int c, int v)
153 return d.set(r, c, v);
155 template<> bool set(types::SparseBool & d, int r, int c, int v)
157 return d.set(r, c, v != 0);
161 * TODO report possible bug in Eigen when inserting 0. invalidates Eigen::InnerIterator
163 template<> bool set(types::Sparse::RealSparse_t& s, int r, int c, double v)
172 template<> bool set(types::Sparse::RealSparse_t& s, int r, int c, std::complex<double> v)
176 s.insert(r, c) = v.real();
180 // should we make this a compile error ?
181 template<> bool set(types::Sparse::CplxSparse_t& s, int r, int c, double v)
185 s.insert(r, c) = std::complex<double>(v);
192 std::complex<double> const cplxZero(0., 0.);
194 template<> bool set(types::Sparse::CplxSparse_t& s, int r, int c, std::complex<double> v)
203 template<> bool set(types::SparseBool::BoolSparse_t& s, int r, int c, bool v)
215 template<typename S> int rows(S SPARSE_CONST&s)
219 template<typename S> int cols(S SPARSE_CONST&s)
224 template<> int rows(types::Double SPARSE_CONST&d)
228 template<> int cols(types::Double SPARSE_CONST&d)
232 template<> int rows(types::Sparse SPARSE_CONST&s)
236 template<> int cols(types::Sparse SPARSE_CONST&s)
240 template<> int rows(types::Bool SPARSE_CONST&s)
244 template<> int cols(types::Bool SPARSE_CONST&s)
248 template<> int rows(types::SparseBool SPARSE_CONST&s)
252 template<> int cols(types::SparseBool SPARSE_CONST&s)
260 These free function overloads handle nb of rows size queries for 2D containers
261 wrapping the corresponding member function.
262 @param s : 2D structure to query
265 template<typename S> inline int rows(S SPARSE_CONST&s);
266 template<> inline int rows(types::Double SPARSE_CONST&d);
269 These free function overloads handle nb of cols size queries for 2D containers
270 wrapping the corresponding member function.
271 @param s : 2D structure to query
274 template<typename S> inline int cols(S SPARSE_CONST&s);
275 template<> inline int cols(types::Double SPARSE_CONST&d);
277 /* this proxy struct provides read and write access (using set and get)
278 with the usual operators (operator*() and operator=() )*/
279 template<typename S, typename V> struct Accessor
282 @param s_ : 2D structure to access
283 @param r_ : row to access
284 @param c_ ; column to access
286 Accessor(S& s_, int r_, int c_): s(s_), r(r_), c(c_) {}
288 read accessor as a casting operator
289 @return : value of s at (r,c)
291 operator V() SPARSE_CONST
293 // std::cerr<<"reading "<<get<S,V>(s, r, c)<<" @("<<r<<","<<c<<")\n";
294 return ::get<V>(s, r, c);
297 write accessor as an assignment operator
298 @param v : value to set at (r,c) in s.
300 template<typename Sa, typename Va>
301 Accessor& operator=(Accessor<Sa, Va> const& a)
303 // std::cerr<<"writing "<<( Va(const_cast<Accessor<Sa, Va>&>(a)))<<" @("<<r<<","<<c<<")\n";
304 // Va tmp=const_cast<Accessor<Sa, Va>&>(a);
305 // ::set<S,V>(s, r, c, tmp);
306 ::set<S, V>(s, r, c, Va(const_cast<Accessor<Sa, Va>&>(a)));
310 Accessor& operator=(Accessor const& a)
312 // std::cerr<<"writing "<<( V(const_cast<Accessor&>(a)))<<" @("<<r<<","<<c<<")\n";
313 ::set<S, V>(s, r, c, V(const_cast<Accessor&>(a)));
316 Accessor& operator=(V const& v)
318 // std::cerr<<"writing "<<v<<" @("<<r<<","<<c<<")\n";
319 ::set<S, V>(s, r, c, v);
327 /* convenient typedef for pairs of (row, column) int values used as 2D coords */
328 typedef std::pair<int, int> Coords2D;
329 /* convenient typedef for iterator over pairs of (row, column) int values used as 2D coords */
330 typedef std::iterator<std::forward_iterator_tag, Coords2D > Coords2DIterator;
332 Iterator over coords making a full row-wise traversal wrapping around when reaching
333 the end of the 2D container.
335 struct RowWiseFullIterator : Coords2DIterator
338 @param cMax : size of the 2D structure
340 RowWiseFullIterator(Coords2D cMax): c(0, 0), cMax(cMax)
344 @param cMax : size of the 2D structure
345 @param cInit : starting coords of the traversal.
347 RowWiseFullIterator(Coords2D cMax, Coords2D cInit): c(cInit), cMax(cMax)
351 @param rm : nb of rows of the 2D structure
352 @param cm : nb of column of the 2D structure
354 RowWiseFullIterator(int rm, int cm): c(0, 0), cMax(rm, cm)
358 @param rm : nb of rows of the 2D structure
359 @param cm : nb of column of the 2D structure
360 @param rInit : starting row of the traversal
361 @param cInit : starting column of the traversal
363 RowWiseFullIterator(int rm, int cm, int rInit, int cInit): c(rInit, cInit), cMax(rm, cm)
366 RowWiseFullIterator& operator++()
368 if (++c.first == cMax.first)
371 if (++c.second == cMax.second)
374 c.first = c.second = 0;
379 RowWiseFullIterator operator++(int)
381 RowWiseFullIterator tmp(*this);
385 std::pair<int, int> operator*() const
395 Iterator over coords making a row-wise traversal of non zero elements of an Eigen Sparse Matrix
397 template<typename Sp>
398 struct RowWiseSparseIterator : Coords2DIterator
401 @param sp: sparse matrix for non zero elements traversal
403 RowWiseSparseIterator(Sp const& sp): sp(sp), outerIdx(0), innerIt(sp, 0)
406 RowWiseSparseIterator& operator++()
411 if (++outerIdx >= sp.outerSize())
415 new (&innerIt) typename Sp::InnerIterator(sp, outerIdx);// innerIt= typename Sp::InnerIterator(sp, outerIdx) when Eigen will be fixed
419 RowWiseSparseIterator operator++(int)
421 RowWiseFullIterator tmp(*this);
425 std::pair<int, int> operator*() const
427 // std::cerr<<"sparse it r="<<innerIt.row()<<" c="<<innerIt.col()<<std::endl;
428 return std::pair<int, int>(innerIt.row(), innerIt.col());
432 typename Eigen::internal::traits<Sp>::Index outerIdx;
433 typename Sp::InnerIterator innerIt;
437 translate an iterator
439 template<typename C2DIter>
440 struct TranslatedIterator : Coords2DIterator
443 @param C2DIter: translation as a vector of (rows, cols)
444 @param tr: translation as a vector of (rows, cols)
446 TranslatedIterator(C2DIter const& c2dIter, Coords2D tr): it(c2dIter), tr(tr)
449 TranslatedIterator& operator++()
454 TranslatedIterator operator++(int)
456 TranslatedIterator tmp(*this);
460 std::pair<int, int> operator*() const
462 std::pair<int, int>res(*it);
463 res.first += tr.first;
464 res.second += tr.second;
465 // std::cerr<<"translated it r="<< res.first<<" c="<<res.second<<std::endl;
475 * Template for iterator over 2D coords from an int*.
476 * Could handle wrap around with a length arg (i.e. to recycle values instead of raising
477 * "error 15 Submatrix incorrectly defined."
479 template<bool AsVector = false> struct Coords : Coords2DIterator
481 Coords(int SPARSE_CONST* coords, int unused = 0): coords(coords), unused(unused)
491 Coords& operator++(int)
498 Coords2D operator*()const
500 return Coords2D(coords[0] - 1, coords[1] - 1);
508 explicit specialization for 2D from 1D int* sequences
509 (The 2D strcture is considered as a vector)
511 template<> struct Coords<true> : Coords2DIterator
513 Coords(int SPARSE_CONST* coords, int rMax): coords(coords), rMax(rMax)
523 Coords operator++(int)
530 Coords2D operator*()const
532 return Coords2D((coords[0] - 1) % rMax, (coords[0] - 1) / rMax);
539 /* This 'iterator' class allows traverses the 2D containers, either
540 Rowwisefull traversal
541 or with 2D coords from another matrix
542 or with 1D coords from another vector (1x) matrix
543 to respect Double insert() API, we take int* and a bool
545 template<typename S, typename V, typename Iter>
546 struct MatrixIterator : std::iterator<std::forward_iterator_tag, V>
548 MatrixIterator(S& s_, Iter i_): s(s_), i(i_)
551 MatrixIterator& operator++()
556 MatrixIterator operator++(int)
558 MatrixIterator tmp(*this);
562 Accessor<S, V> operator*()
564 return Accessor<S, V>(s, (*i).first, (*i).second);
570 template<typename V, typename S, typename Iter>
571 MatrixIterator<S, V, Iter> makeMatrixIterator(S& s, Iter i)
573 return MatrixIterator<S, V, Iter>(s, i);
576 template<typename S> struct IteratorFromVar;
578 template<typename S> IteratorFromVar<S> makeIteratorFromVar(S& s);
582 Adjacency(double const* x, double const*a): xadj(x), adjncy(a) {}
584 double const* adjncy;
587 template<typename In, typename Sz, typename Out>
588 Out mycopy_n(In i, Sz n, Out o)
590 for (; n; --n, ++i, ++o)
597 template<typename T> std::size_t nonZeros(T SPARSE_CONST& t)
601 template<> std::size_t nonZeros(types::Sparse SPARSE_CONST& sp)
603 return sp.nonZeros();
605 template<typename Scalar, int Options, typename Index> std::size_t nonZeros(Eigen::SparseMatrix<Scalar, Options, Index> SPARSE_CONST& sp)
607 return sp.nonZeros();
611 /* Default for dense matrix Scilab matrix types
613 template<typename D> RowWiseFullIterator makeNonZerosIterator(D SPARSE_CONST& d)
615 return RowWiseFullIterator(d.getRows(), d.getCols());
617 template<typename Scalar, int Options, typename Index> RowWiseSparseIterator<Eigen::SparseMatrix<Scalar, Options, Index> > makeNonZerosIterator(Eigen::SparseMatrix<Scalar, Options, Index> SPARSE_CONST& sp)
619 return RowWiseSparseIterator<Eigen::SparseMatrix<Scalar, Options, Index> >(sp);
621 template<typename Iter> TranslatedIterator<Iter> makeTranslatedIterator(Iter const& it, Coords2D const& tr)
623 return TranslatedIterator<Iter>(it, tr);
628 template<typename S> struct IteratorFromVar { };
630 template<> struct IteratorFromVar<types::Double> : Coords2DIterator
632 IteratorFromVar(types::Double& d_): d(d_), r(0)
637 IteratorFromVar& operator++()
642 IteratorFromVar operator++(int)
644 IteratorFromVar tmp(*this);
650 return std::pair<int, int>(static_cast<int>(d.getReal(r, 0) - 1), static_cast<int>(d.getReal(r, 1) - 1));
658 iterator from adjacency matrices :
660 template<> struct IteratorFromVar<Adjacency> : Coords2DIterator
662 IteratorFromVar(Adjacency& a): xadj(a.xadj), adjncy(a.adjncy), c(1), nb(1)
667 IteratorFromVar& operator++()
674 IteratorFromVar operator++(int)
676 IteratorFromVar tmp(*this);
682 std::pair<int, int> operator*()
684 return std::pair<int, int>(static_cast<int>(*adjncy) - 1, c - 1);
689 for (; xadj[1] <= nb; ++c, ++xadj)
694 double const* adjncy;
699 template<typename S> IteratorFromVar<S> makeIteratorFromVar(S& s)
701 return IteratorFromVar<S>(s);