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 CONST&, int, int)
49 return UndefinedAccessorForType<S>();
52 template<> double get(types::Double CONST& d, int r, int c)
54 return d.getReal(r, c);
56 template<> std::complex<double> get(types::Double 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 CONST& d, int r, int c)
63 return d.get(r, c) == 1;
65 template<> int get(types::Bool CONST& d, int r, int c)
69 template<> bool get(types::SparseBool CONST& d, int r, int c)
73 template<> int get(types::SparseBool CONST& d, int r, int c)
78 template<> double get(types::Sparse CONST& s, int r, int c)
80 return s.getReal(r, c);
82 template<> std::complex<double> get(types::Sparse CONST& s, int r, int c)
87 template<> double get(Eigen::SparseMatrix<double, 0, int> CONST&s, int r, int c)
91 template<> std::complex<double> get(Eigen::SparseMatrix<double, 0, int> CONST&s, int r, int c)
93 return std::complex<double>(s.coeff(r, c), 0.);
96 template<> bool get(Eigen::SparseMatrix<bool> CONST& d, int r, int c)
101 template<> double get(Eigen::SparseMatrix<std::complex<double>, 0, int> CONST&s, int r, int c)
103 return s.coeff(r, c).real();
105 template<> std::complex<double> get(Eigen::SparseMatrix<std::complex<double>, 0, int> 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(Eigen::SparseMatrix<double, 0, int>& s, int r, int c, double v)
172 template<> bool set(Eigen::SparseMatrix<double, 0, int>& 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(Eigen::SparseMatrix<std::complex<double>, 0, int>& 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(Eigen::SparseMatrix<std::complex<double>, 0, int>& s, int r, int c, std::complex<double> v)
203 template<> bool set(Eigen::SparseMatrix<bool>& s, int r, int c, bool v)
215 template<typename S> int rows(S CONST&s)
219 template<typename S> int cols(S CONST&s)
224 template<> int rows(types::Double CONST&d)
228 template<> int cols(types::Double CONST&d)
232 template<> int rows(types::Sparse CONST&s)
236 template<> int cols(types::Sparse CONST&s)
240 template<> int rows(types::Bool CONST&s)
244 template<> int cols(types::Bool CONST&s)
248 template<> int rows(types::SparseBool CONST&s)
252 template<> int cols(types::SparseBool 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 CONST&s);
266 template<> inline int rows(types::Double 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 CONST&s);
275 template<> inline int cols(types::Double 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)
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 CONST* coords, int unused = 0): coords(coords)
491 Coords& operator++(int)
498 Coords2D operator*()const
500 return Coords2D(coords[0] - 1, coords[1] - 1);
507 explicit specialization for 2D from 1D int* sequences
508 (The 2D strcture is considered as a vector)
510 template<> struct Coords<true> : Coords2DIterator
512 Coords(int CONST* coords, int rMax): coords(coords), rMax(rMax)
522 Coords operator++(int)
529 Coords2D operator*()const
531 return Coords2D((coords[0] - 1) % rMax, (coords[0] - 1) / rMax);
538 /* This 'iterator' class allows traverses the 2D containers, either
539 Rowwisefull traversal
540 or with 2D coords from another matrix
541 or with 1D coords from another vector (1x) matrix
542 to respect Double insert() API, we take int* and a bool
544 template<typename S, typename V, typename Iter>
545 struct MatrixIterator : std::iterator<std::forward_iterator_tag, V>
547 MatrixIterator(S& s_, Iter i_): s(s_), i(i_)
550 MatrixIterator& operator++()
555 MatrixIterator operator++(int)
557 MatrixIterator tmp(*this);
561 Accessor<S, V> operator*()
563 return Accessor<S, V>(s, (*i).first, (*i).second);
569 template<typename V, typename S, typename Iter>
570 MatrixIterator<S, V, Iter> makeMatrixIterator(S& s, Iter i)
572 return MatrixIterator<S, V, Iter>(s, i);
575 template<typename S> struct IteratorFromVar;
577 template<typename S> IteratorFromVar<S> makeIteratorFromVar(S& s);
581 Adjacency(double const* x, double const*a): xadj(x), adjncy(a) {}
583 double const* adjncy;
586 template<typename In, typename Sz, typename Out>
587 Out mycopy_n(In i, Sz n, Out o)
589 for (; n; --n, ++i, ++o)
596 template<typename T> std::size_t nonZeros(T CONST& t)
600 template<> std::size_t nonZeros(types::Sparse CONST& sp)
602 return sp.nonZeros();
604 template<typename Scalar, int Options, typename Index> std::size_t nonZeros(Eigen::SparseMatrix<Scalar, Options, Index> CONST& sp)
606 return sp.nonZeros();
610 /* Default for dense matrix Scilab matrix types
612 template<typename D> RowWiseFullIterator makeNonZerosIterator(D CONST& d)
614 return RowWiseFullIterator(d.getRows(), d.getCols());
616 template<typename Scalar, int Options, typename Index> RowWiseSparseIterator<Eigen::SparseMatrix<Scalar, Options, Index> > makeNonZerosIterator(Eigen::SparseMatrix<Scalar, Options, Index> CONST& sp)
618 return RowWiseSparseIterator<Eigen::SparseMatrix<Scalar, Options, Index> >(sp);
620 template<typename Iter> TranslatedIterator<Iter> makeTranslatedIterator(Iter const& it, Coords2D const& tr)
622 return TranslatedIterator<Iter>(it, tr);
627 template<typename S> struct IteratorFromVar { };
629 template<> struct IteratorFromVar<types::Double> : Coords2DIterator
631 IteratorFromVar(types::Double& d_): d(d_), r(0)
636 IteratorFromVar& operator++()
641 IteratorFromVar operator++(int)
643 IteratorFromVar tmp(*this);
649 return std::pair<int, int>(static_cast<int>(d.getReal(r, 0) - 1), static_cast<int>(d.getReal(r, 1) - 1));
657 iterator from adjacency matrices :
659 template<> struct IteratorFromVar<Adjacency> : Coords2DIterator
661 IteratorFromVar(Adjacency& a): xadj(a.xadj), adjncy(a.adjncy), c(1), nb(1)
666 IteratorFromVar& operator++()
673 IteratorFromVar operator++(int)
675 IteratorFromVar tmp(*this);
681 std::pair<int, int> operator*()
683 return std::pair<int, int>(static_cast<int>(*adjncy) - 1, c - 1);
688 for (; xadj[1] <= nb; ++c, ++xadj)
693 double const* adjncy;
698 template<typename S> IteratorFromVar<S> makeIteratorFromVar(S& s)
700 return IteratorFromVar<S>(s);